1 | //
|
---|
2 | // csgmat.cc
|
---|
3 | //
|
---|
4 | // Copyright (C) 1996 Limit Point Systems, Inc.
|
---|
5 | //
|
---|
6 | // Author: Ida Nielsen <ida@kemi.aau.dk>
|
---|
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 <string.h>
|
---|
29 | #include <stdlib.h>
|
---|
30 | #include <math.h>
|
---|
31 | #include <limits.h>
|
---|
32 |
|
---|
33 | #include <util/misc/timer.h>
|
---|
34 | #include <util/misc/formio.h>
|
---|
35 | #include <math/scmat/matrix.h>
|
---|
36 | #include <math/scmat/local.h>
|
---|
37 | #include <math/scmat/repl.h>
|
---|
38 | #include <chemistry/qc/mbpt/mbpt.h>
|
---|
39 | #include <chemistry/qc/basis/petite.h>
|
---|
40 | #include <chemistry/qc/scf/lgbuild.h>
|
---|
41 | #include <chemistry/qc/scf/clhftmpl.h>
|
---|
42 |
|
---|
43 | using namespace sc;
|
---|
44 |
|
---|
45 | #define ioff(i) (((i)*((i)+1))>>1)
|
---|
46 | #define IOFF(a,b) (((a)>(b))?(ioff(a)+(b)):(ioff(b)+(a)))
|
---|
47 |
|
---|
48 | #define INT_MAX1(n1) ((n1)-1)
|
---|
49 | #define INT_MAX2(e12,i,n2) ((e12)?(i):((n2)-1))
|
---|
50 | #define INT_MAX3(e13e24,i,n3) ((e13e24)?(i):((n3)-1))
|
---|
51 | #define INT_MAX4(e13e24,e34,i,j,k,n4) \
|
---|
52 | ((e34)?(((e13e24)&&((k)==(i)))?(j):(k)) \
|
---|
53 | :((e13e24)&&((k)==(i)))?(j):(n4)-1)
|
---|
54 |
|
---|
55 | enum Access { Read, Write, Accum };
|
---|
56 | static RefSymmSCMatrix
|
---|
57 | get_local_data(const RefSymmSCMatrix& m, double*& p,
|
---|
58 | const Ref<MessageGrp> &msg, Access access)
|
---|
59 | {
|
---|
60 | RefSymmSCMatrix l = m;
|
---|
61 |
|
---|
62 | if (!dynamic_cast<LocalSymmSCMatrix*>(l.pointer())
|
---|
63 | && !dynamic_cast<ReplSymmSCMatrix*>(l.pointer())) {
|
---|
64 | Ref<SCMatrixKit> k = new ReplSCMatrixKit;
|
---|
65 | l = k->symmmatrix(m.dim());
|
---|
66 | l->convert(m);
|
---|
67 |
|
---|
68 | if (access == Accum)
|
---|
69 | l->assign(0.0);
|
---|
70 | } else if (msg->n() > 1 && access==Accum) {
|
---|
71 | l = m.clone();
|
---|
72 | l.assign(0.0);
|
---|
73 | }
|
---|
74 |
|
---|
75 | if (dynamic_cast<ReplSymmSCMatrix*>(l.pointer()))
|
---|
76 | p = dynamic_cast<ReplSymmSCMatrix*>(l.pointer())->get_data();
|
---|
77 | else
|
---|
78 | p = dynamic_cast<LocalSymmSCMatrix*>(l.pointer())->get_data();
|
---|
79 |
|
---|
80 | return l;
|
---|
81 | }
|
---|
82 |
|
---|
83 | static signed char *
|
---|
84 | init_pmax(double *pmat_data, const Ref<GaussianBasisSet> &basis)
|
---|
85 | {
|
---|
86 | double l2inv = 1.0/log(2.0);
|
---|
87 | double tol = pow(2.0,-126.0);
|
---|
88 |
|
---|
89 | GaussianBasisSet& gbs = *basis.pointer();
|
---|
90 |
|
---|
91 | signed char * pmax = new signed char[ioff(gbs.nshell())];
|
---|
92 |
|
---|
93 | int ish, jsh, ij;
|
---|
94 | for (ish=ij=0; ish < gbs.nshell(); ish++) {
|
---|
95 | int istart = gbs.shell_to_function(ish);
|
---|
96 | int iend = istart + gbs(ish).nfunction();
|
---|
97 |
|
---|
98 | for (jsh=0; jsh <= ish; jsh++,ij++) {
|
---|
99 | int jstart = gbs.shell_to_function(jsh);
|
---|
100 | int jend = jstart + gbs(jsh).nfunction();
|
---|
101 |
|
---|
102 | double maxp=0, tmp;
|
---|
103 |
|
---|
104 | for (int i=istart; i < iend; i++) {
|
---|
105 | int ijoff = ioff(i) + jstart;
|
---|
106 | for (int j=jstart; j < ((ish==jsh) ? i+1 : jend); j++,ijoff++)
|
---|
107 | if ((tmp=::fabs(pmat_data[ijoff])) > maxp)
|
---|
108 | maxp=tmp;
|
---|
109 | }
|
---|
110 |
|
---|
111 | if (maxp <= tol)
|
---|
112 | maxp=tol;
|
---|
113 |
|
---|
114 | long power = long(log(maxp)*l2inv);
|
---|
115 | if (power < SCHAR_MIN) pmax[ij] = SCHAR_MIN;
|
---|
116 | else if (power > SCHAR_MAX) pmax[ij] = SCHAR_MAX;
|
---|
117 | else pmax[ij] = (signed char) power;
|
---|
118 | }
|
---|
119 | }
|
---|
120 |
|
---|
121 | return pmax;
|
---|
122 | }
|
---|
123 |
|
---|
124 | /**************************************************************************
|
---|
125 | *
|
---|
126 | * calculate the closed shell G matrix
|
---|
127 | * assume all matrices are held locally -- IMBN
|
---|
128 | *
|
---|
129 | * input:
|
---|
130 | * Gmat = matrix containing old G matrix
|
---|
131 | * DPmat = matrix containing density diff matrix
|
---|
132 | *
|
---|
133 | * on return:
|
---|
134 | * Gmat contains the new G matrix
|
---|
135 | *
|
---|
136 | * return 0 on success and -1 on failure
|
---|
137 | */
|
---|
138 |
|
---|
139 | int
|
---|
140 | MBPT2::make_cs_gmat_new(RefSymmSCMatrix& Gmat,
|
---|
141 | const RefSymmSCMatrix& DPmat)
|
---|
142 | {
|
---|
143 | int i;
|
---|
144 | int nthread = thr_->nthread();
|
---|
145 |
|
---|
146 | tim_enter("gmat");
|
---|
147 |
|
---|
148 | Ref<PetiteList> pl = integral()->petite_list(basis());
|
---|
149 |
|
---|
150 | Gmat.assign(0.0);
|
---|
151 |
|
---|
152 | // scale the off-diagonal elements of DPmat by 2.0
|
---|
153 | DPmat->scale(2.0);
|
---|
154 | DPmat->scale_diagonal(0.5);
|
---|
155 |
|
---|
156 | // now try to figure out the matrix specialization we're dealing with
|
---|
157 | // if we're using Local matrices, then there's just one subblock, or
|
---|
158 | // see if we can convert G and P to local matrices
|
---|
159 |
|
---|
160 | if (debug_>1) {
|
---|
161 | DPmat.print("DPmat before build");
|
---|
162 | }
|
---|
163 |
|
---|
164 | // grab the data pointers from the G and P matrices
|
---|
165 | double *gmat, *pmat;
|
---|
166 | RefSymmSCMatrix gtmp = get_local_data(Gmat, gmat, msg_, Accum);
|
---|
167 | RefSymmSCMatrix ptmp = get_local_data(DPmat, pmat, msg_, Read);
|
---|
168 |
|
---|
169 | signed char * pmax = init_pmax(pmat, basis());
|
---|
170 |
|
---|
171 | LocalGBuild<LocalCLHFContribution> **gblds =
|
---|
172 | new LocalGBuild<LocalCLHFContribution>*[nthread];
|
---|
173 | LocalCLHFContribution **conts = new LocalCLHFContribution*[nthread];
|
---|
174 |
|
---|
175 | double **gmats = new double*[nthread];
|
---|
176 | gmats[0] = gmat;
|
---|
177 |
|
---|
178 | Ref<GaussianBasisSet> bs = basis();
|
---|
179 | int ntri = ioff(bs->nbasis());
|
---|
180 |
|
---|
181 | for (i=0; i < nthread; i++) {
|
---|
182 | if (i) {
|
---|
183 | gmats[i] = new double[ntri];
|
---|
184 | memset(gmats[i], 0, sizeof(double)*ntri);
|
---|
185 | }
|
---|
186 | conts[i] = new LocalCLHFContribution(gmats[i], pmat);
|
---|
187 | gblds[i] = new LocalGBuild<LocalCLHFContribution>(*conts[i], tbints_[i],
|
---|
188 | pl, bs, msg_, pmax, cphf_epsilon_/1000.0, nthread, i
|
---|
189 | );
|
---|
190 |
|
---|
191 | thr_->add_thread(i, gblds[i]);
|
---|
192 | }
|
---|
193 |
|
---|
194 | if (thr_->start_threads() < 0) {
|
---|
195 | ExEnv::err0() << indent
|
---|
196 | << "MBPT: csgmat: error starting threads" << std::endl;
|
---|
197 | abort();
|
---|
198 | }
|
---|
199 |
|
---|
200 | if (thr_->wait_threads() < 0) {
|
---|
201 | ExEnv::err0() << indent
|
---|
202 | << "MBPT: csgmat: error waiting for threads" << std::endl;
|
---|
203 | abort();
|
---|
204 | }
|
---|
205 |
|
---|
206 | double tnint=0;
|
---|
207 | for (i=0; i < nthread; i++) {
|
---|
208 | tnint += gblds[i]->tnint;
|
---|
209 |
|
---|
210 | if (i) {
|
---|
211 | for (int j=0; j < ntri; j++)
|
---|
212 | gmat[j] += gmats[i][j];
|
---|
213 | delete[] gmats[i];
|
---|
214 | }
|
---|
215 |
|
---|
216 | delete gblds[i];
|
---|
217 | delete conts[i];
|
---|
218 | }
|
---|
219 |
|
---|
220 | delete[] gmats;
|
---|
221 | delete[] gblds;
|
---|
222 | delete[] conts;
|
---|
223 | delete[] pmax;
|
---|
224 |
|
---|
225 | msg_->sum(&tnint, 1, 0, 0);
|
---|
226 | //ExEnv::out0() << indent << scprintf("%20.0f integrals\n", tnint);
|
---|
227 |
|
---|
228 | // if we're running on multiple processors, then sum the G matrix
|
---|
229 | if (msg_->n() > 1)
|
---|
230 | msg_->sum(gmat, ioff(basis()->nbasis()));
|
---|
231 |
|
---|
232 | // if we're running on multiple processors, or we don't have local
|
---|
233 | // matrices, then accumulate gtmp back into G
|
---|
234 | int local = (dynamic_cast<LocalSCMatrixKit*>(basis()->matrixkit().pointer()) ||
|
---|
235 | dynamic_cast<ReplSCMatrixKit*>(basis()->matrixkit().pointer())) ? 1:0;
|
---|
236 | if (!local || msg_->n() > 1)
|
---|
237 | Gmat->convert_accumulate(gtmp);
|
---|
238 |
|
---|
239 | // now symmetrize the skeleton G matrix, placing the result in dd
|
---|
240 | Gmat.scale(1.0/(double)pl->order());
|
---|
241 | RefSymmSCMatrix Gmat_so(so_dimension(), basis_matrixkit());
|
---|
242 | if (debug_>1) {
|
---|
243 | Gmat.print("skeleton Gmat before symmetrize");
|
---|
244 | }
|
---|
245 | pl->symmetrize(Gmat,Gmat_so);
|
---|
246 | if (debug_>1) {
|
---|
247 | Gmat_so.print("Gmat in SO basis");
|
---|
248 | }
|
---|
249 | Gmat = pl->to_AO_basis(Gmat_so);
|
---|
250 | if (debug_>1) {
|
---|
251 | Gmat.print("Gmat in AO basis");
|
---|
252 | }
|
---|
253 | BlockedSymmSCMatrix *blocked_Gmat = dynamic_cast<BlockedSymmSCMatrix*>(Gmat.pointer());
|
---|
254 | if (!blocked_Gmat || blocked_Gmat->nblocks() != 1) {
|
---|
255 | ExEnv::outn() << "csgmat.cc: Gmat is wrong type" << std::endl;
|
---|
256 | abort();
|
---|
257 | }
|
---|
258 | Gmat = blocked_Gmat->block(0);
|
---|
259 |
|
---|
260 | tim_exit("gmat");
|
---|
261 |
|
---|
262 | return 0;
|
---|
263 | }
|
---|
264 |
|
---|
265 | int
|
---|
266 | MBPT2::make_cs_gmat(RefSymmSCMatrix& Gmat, double *DPmat)
|
---|
267 | {
|
---|
268 | int errcod;
|
---|
269 |
|
---|
270 | tim_enter("gmat");
|
---|
271 |
|
---|
272 | errcod = make_g_d_nor(Gmat, DPmat, intbuf_);
|
---|
273 |
|
---|
274 | if (errcod != 0) {
|
---|
275 | fprintf(stderr,"mbpt_gmat: trouble forming gmat 3\n");
|
---|
276 | return -1;
|
---|
277 | }
|
---|
278 |
|
---|
279 | tim_exit("gmat");
|
---|
280 |
|
---|
281 | return 0;
|
---|
282 | }
|
---|
283 |
|
---|
284 | /************************************************************************
|
---|
285 | *
|
---|
286 | * Form the vector maxp; each element of maxp is the 2-based log of the
|
---|
287 | * largest element (absolute value) in a block of the density matrix
|
---|
288 | * (DPmat). The density matrix is of dimension nbasis x nbasis
|
---|
289 | *
|
---|
290 | ************************************************************************/
|
---|
291 |
|
---|
292 | void
|
---|
293 | MBPT2::form_max_dens(double *DPmat, signed char *maxp)
|
---|
294 | {
|
---|
295 |
|
---|
296 | int i, j, k, l, ij;
|
---|
297 | int isize, jsize, ioffset, joffset;
|
---|
298 | double linv = 1.0/log(2.0);
|
---|
299 | double tol = pow(2.0,-126.0);
|
---|
300 | double ftmp, tmp;
|
---|
301 | double *dpmat_ptr;
|
---|
302 |
|
---|
303 | for (i=0; i<basis()->nshell(); i++) {
|
---|
304 | isize = basis()->shell(i).nfunction();
|
---|
305 | ioffset = basis()->shell_to_function(i);
|
---|
306 | for (j=0; j<=i; j++) {
|
---|
307 | jsize = basis()->shell(j).nfunction();
|
---|
308 | joffset = basis()->shell_to_function(j);
|
---|
309 | tmp = 0.0;
|
---|
310 | for (k=0; k<isize; k++) {
|
---|
311 | dpmat_ptr = &DPmat[nbasis*(ioffset+k) + joffset];
|
---|
312 | for (l=0; l<jsize; l++) {
|
---|
313 | ftmp = fabs(*dpmat_ptr++);
|
---|
314 | if (ftmp > tmp) tmp = ftmp;
|
---|
315 | }
|
---|
316 | }
|
---|
317 | tmp = (tmp > tol) ? tmp : tol;
|
---|
318 | ij = i*(i+1)/2 +j;
|
---|
319 | maxp[ij] = (signed char) (log(tmp)*linv);
|
---|
320 | /* log(tmp)/linv equals the 2-based log of tmp */
|
---|
321 | }
|
---|
322 | }
|
---|
323 |
|
---|
324 | }
|
---|
325 |
|
---|
326 | int
|
---|
327 | MBPT2::init_cs_gmat()
|
---|
328 | {
|
---|
329 | tbint_ = integral()->electron_repulsion();
|
---|
330 | tbint_->set_redundant(0);
|
---|
331 | intbuf_ = tbint_->buffer();
|
---|
332 | return 1;
|
---|
333 | }
|
---|
334 |
|
---|
335 | void
|
---|
336 | MBPT2::done_cs_gmat()
|
---|
337 | {
|
---|
338 | tbint_ = 0;
|
---|
339 | intbuf_ = 0;
|
---|
340 | }
|
---|
341 |
|
---|
342 | int
|
---|
343 | MBPT2::make_g_d_nor(RefSymmSCMatrix& Gmat,
|
---|
344 | double *DPmat, const double *mgdbuff)
|
---|
345 | {
|
---|
346 | int tmax,imax,cpmax,pmaxijk=0;
|
---|
347 | int pmaxik,pmaxjk,pmaxij=0;
|
---|
348 | int i,j,k,l;
|
---|
349 | int ij,kl;
|
---|
350 | int n1,n2,n3,n4;
|
---|
351 | int e12,e34,e13e24,e_any;
|
---|
352 | int bf1,bf2,bf3,bf4;
|
---|
353 | int i1,j1,k1,l1;
|
---|
354 | int i2,j2,k2,l2;
|
---|
355 | int ii,jj,kk,ll;
|
---|
356 | int ij1;
|
---|
357 | int lij,lkl;
|
---|
358 | int index;
|
---|
359 | int int_index,kindex;
|
---|
360 | int nproc=msg_->n();
|
---|
361 | int me=msg_->me();
|
---|
362 | int s1,s2,s3,s4;
|
---|
363 | int nbatri = (nbasis*(nbasis+1))/2;
|
---|
364 |
|
---|
365 | double tol = desired_gradient_accuracy() / 1000.0;
|
---|
366 | if (min_orthog_res() < 1.0) { tol *= min_orthog_res(); }
|
---|
367 | int inttol = (int) (log(tol)/log(2.0));
|
---|
368 |
|
---|
369 | double tnint=0.0;
|
---|
370 | double pki_int,value;
|
---|
371 | double *gtmp=0, *ptmp=0;
|
---|
372 | double *dpmat_ptr;
|
---|
373 |
|
---|
374 | char *shnfunc=0;
|
---|
375 | signed char *maxp=0;
|
---|
376 |
|
---|
377 |
|
---|
378 | // Scale DPmat; this is necessary when using the gmat formation
|
---|
379 | // program from scf (modified slightly), since this program assumes
|
---|
380 | // that the off-diagonal elements have been scaled by a factor of 2.0
|
---|
381 | dpmat_ptr = DPmat;
|
---|
382 | for (i=0; i<nbasis; i++) {
|
---|
383 | for (j=0; j<nbasis; j++) {
|
---|
384 | if (i != j) *dpmat_ptr++ *= 2.0;
|
---|
385 | else dpmat_ptr++;
|
---|
386 | }
|
---|
387 | }
|
---|
388 |
|
---|
389 | // Allocate and assign maxp
|
---|
390 | if (eliminate_in_gmat_) {
|
---|
391 | int nshellt = basis()->nshell()*(basis()->nshell()+1)/2;
|
---|
392 | maxp = (signed char*) malloc(sizeof(signed char)*nshellt);
|
---|
393 | if (!(maxp)) {
|
---|
394 | fprintf(stderr,"mkgdlb: could not malloc maxp\n");
|
---|
395 | return -1;
|
---|
396 | }
|
---|
397 | form_max_dens(DPmat, maxp);
|
---|
398 | }
|
---|
399 |
|
---|
400 | // Allocate and assign ptmp (contains lower triangle of DPmat
|
---|
401 | ptmp = (double*) malloc(sizeof(double)*nbatri);
|
---|
402 | if (!(ptmp)) {
|
---|
403 | fprintf(stderr,"mkgdlb: could not malloc ptmp\n");
|
---|
404 | return -1;
|
---|
405 | }
|
---|
406 | for (i=0; i<nbasis; i++) {
|
---|
407 | dpmat_ptr = &DPmat[i*nbasis];
|
---|
408 | for (j=0; j<=i; j++) {
|
---|
409 | ptmp[i*(i+1)/2 + j] = *dpmat_ptr++;
|
---|
410 | }
|
---|
411 | }
|
---|
412 |
|
---|
413 |
|
---|
414 | // "Unscale" DPmat to get the original DPmat
|
---|
415 | dpmat_ptr = DPmat;
|
---|
416 | for (i=0; i<nbasis; i++) {
|
---|
417 | for (j=0; j<nbasis; j++) {
|
---|
418 | if (i != j) *dpmat_ptr++ *= 0.50;
|
---|
419 | else dpmat_ptr++;
|
---|
420 | }
|
---|
421 | }
|
---|
422 |
|
---|
423 | // Allocate and initialize gtmp
|
---|
424 | gtmp = (double *) malloc(sizeof(double)*nbatri);
|
---|
425 | for (i=0; i<nbatri; i++) gtmp[i] = 0.0;
|
---|
426 |
|
---|
427 | // Allocate and assign shnfunc
|
---|
428 | shnfunc = (char *) malloc(basis()->nshell());
|
---|
429 | if (!shnfunc) {
|
---|
430 | fprintf(stderr,"make_g_d_lb: could not malloc shnfunc\n");
|
---|
431 | return -1;
|
---|
432 | }
|
---|
433 | for (i=0; i < basis()->nshell(); i++) shnfunc[i]=basis()->shell(i).nfunction();
|
---|
434 |
|
---|
435 |
|
---|
436 | /********************************************************
|
---|
437 | * Start the actual formation of the G matrix: *
|
---|
438 | * Loop over all shells, calculate a bunch of integrals *
|
---|
439 | * from each shell quartet, and stick those integrals *
|
---|
440 | * where they belong *
|
---|
441 | ********************************************************/
|
---|
442 |
|
---|
443 |
|
---|
444 | kindex=int_index=0;
|
---|
445 | for (i=0; i<basis()->nshell(); i++) {
|
---|
446 |
|
---|
447 | for (j=0; j<=i; j++) {
|
---|
448 | ij = ioff(i)+j;
|
---|
449 | if(eliminate_in_gmat_) pmaxij=maxp[ij];
|
---|
450 |
|
---|
451 | for (k=0; k<=i; k++,kindex++) {
|
---|
452 | if(kindex%nproc!=me) {
|
---|
453 | continue;
|
---|
454 | }
|
---|
455 |
|
---|
456 | kl=ioff(k);
|
---|
457 | if(eliminate_in_gmat_) {
|
---|
458 | pmaxijk=pmaxij;
|
---|
459 | if((pmaxik=maxp[(ioff(i)+k)]-2)>pmaxijk) pmaxijk=pmaxik;
|
---|
460 | if((pmaxjk=maxp[IOFF(j,k)]-2)>pmaxijk) pmaxijk=pmaxjk;
|
---|
461 | }
|
---|
462 |
|
---|
463 | for (l=0; l<=(k==i?j:k); l++) {
|
---|
464 |
|
---|
465 | imax = (int) tbint_->log2_shell_bound(i,j,k,l);
|
---|
466 |
|
---|
467 | if(eliminate_in_gmat_) {
|
---|
468 | cpmax = (maxp[kl]>pmaxijk) ? maxp[kl] : pmaxijk;
|
---|
469 | if((tmax=maxp[(ioff(i)+l)]-2)>cpmax) cpmax=tmax;
|
---|
470 | if((tmax=maxp[IOFF(j,l)]-2)>cpmax) cpmax=tmax;
|
---|
471 |
|
---|
472 | if(cpmax+imax < inttol) {
|
---|
473 | kl++;
|
---|
474 | continue;
|
---|
475 | }
|
---|
476 | }
|
---|
477 |
|
---|
478 | s1 = i; s2 = j; s3 = k; s4 = l;
|
---|
479 |
|
---|
480 | tbint_->compute_shell(s1,s2,s3,s4);
|
---|
481 |
|
---|
482 | n1 = shnfunc[s1];
|
---|
483 | n2 = shnfunc[s2];
|
---|
484 | n3 = shnfunc[s3];
|
---|
485 | n4 = shnfunc[s4];
|
---|
486 |
|
---|
487 | // Shell equivalence information
|
---|
488 | e12 = (s2==s1);
|
---|
489 | e13e24 = (s3==s1) && (s4==s2);
|
---|
490 | e34 = (s4==s3);
|
---|
491 |
|
---|
492 | index = 0;
|
---|
493 |
|
---|
494 | e_any = (e12||e13e24||e34);
|
---|
495 | if(e_any) {
|
---|
496 | for (bf1=0; bf1<=INT_MAX1(n1) ; bf1++) {
|
---|
497 | i2 = basis()->shell_to_function(s1) + bf1;
|
---|
498 |
|
---|
499 | for (bf2=0; bf2<=INT_MAX2(e12,bf1,n2) ; bf2++) {
|
---|
500 | j2 = basis()->shell_to_function(s2) + bf2;
|
---|
501 | if(i2>=j2) { i1=i2; j1=j2; }
|
---|
502 | else { i1=j2; j1=i2; }
|
---|
503 | ij1=ioff(i1)+j1;
|
---|
504 |
|
---|
505 | for (bf3=0; bf3<=INT_MAX3(e13e24,bf1,n3) ; bf3++) {
|
---|
506 | k2 = basis()->shell_to_function(s3) + bf3;
|
---|
507 |
|
---|
508 | for (bf4=0;bf4<=INT_MAX4(e13e24,e34,bf1,bf2,bf3,n4);bf4++){
|
---|
509 | if (fabs(mgdbuff[index])>1.0e-10) {
|
---|
510 | l2 = basis()->shell_to_function(s4) + bf4;
|
---|
511 |
|
---|
512 | if(k2>=l2) { k1=k2; l1=l2; }
|
---|
513 | else { k1=l2; l1=k2; }
|
---|
514 |
|
---|
515 | if(ij1 >= ioff(k1)+l1) {
|
---|
516 | ii = i1; jj = j1; kk = k1; ll = l1;
|
---|
517 | }
|
---|
518 | else {
|
---|
519 | ii = k1; jj = l1; kk = i1; ll = j1;
|
---|
520 | }
|
---|
521 |
|
---|
522 | pki_int = mgdbuff[index];
|
---|
523 |
|
---|
524 | if (jj == kk) {
|
---|
525 | if (ii == jj || kk == ll) {
|
---|
526 | lij=ioff(ii)+jj;
|
---|
527 | lkl=ioff(kk)+ll;
|
---|
528 | value=(lij==lkl)? 0.25*pki_int: 0.5*pki_int;
|
---|
529 | gtmp[lij] += ptmp[lkl]*value;
|
---|
530 | gtmp[lkl] += ptmp[lij]*value;
|
---|
531 | }
|
---|
532 | else {
|
---|
533 | lij=ioff(ii)+jj;
|
---|
534 | lkl=ioff(kk)+ll;
|
---|
535 | value=(lij==lkl)? 0.375*pki_int: 0.75*pki_int;
|
---|
536 | gtmp[lij] += ptmp[lkl]*value;
|
---|
537 | gtmp[lkl] += ptmp[lij]*value;
|
---|
538 |
|
---|
539 | lij=ioff(ii)+ll;
|
---|
540 | lkl=IOFF(kk,jj);
|
---|
541 | value=(lij==lkl)? 0.25*pki_int: 0.5*pki_int;
|
---|
542 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
543 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
544 | }
|
---|
545 | }
|
---|
546 | else if (ii == kk || jj == ll) {
|
---|
547 | lij=ioff(ii)+jj;
|
---|
548 | lkl=ioff(kk)+ll;
|
---|
549 | value=(lij==lkl)? 0.375*pki_int: 0.75*pki_int;
|
---|
550 | gtmp[lij] += ptmp[lkl]*value;
|
---|
551 | gtmp[lkl] += ptmp[lij]*value;
|
---|
552 |
|
---|
553 | lij=ioff(ii)+kk;
|
---|
554 | lkl=IOFF(jj,ll);
|
---|
555 | value=(lij==lkl)? 0.25*pki_int : 0.5*pki_int;
|
---|
556 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
557 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
558 | }
|
---|
559 | else {
|
---|
560 | lij=ioff(ii)+jj;
|
---|
561 | lkl=ioff(kk)+ll;
|
---|
562 | value=(lij==lkl)? 0.5*pki_int : pki_int;
|
---|
563 | gtmp[lij] += ptmp[lkl]*value;
|
---|
564 | gtmp[lkl] += ptmp[lij]*value;
|
---|
565 |
|
---|
566 | lij=ioff(ii)+kk;
|
---|
567 | lkl=IOFF(jj,ll);
|
---|
568 | value=(lij==lkl)? 0.125*pki_int: 0.25*pki_int;
|
---|
569 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
570 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
571 |
|
---|
572 | if((ii != jj) && (kk != ll)) {
|
---|
573 | lij=ioff(ii)+ll;
|
---|
574 | lkl=IOFF(kk,jj);
|
---|
575 | value=(lij==lkl)? 0.125*pki_int: 0.25*pki_int;
|
---|
576 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
577 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
578 | }
|
---|
579 | }
|
---|
580 | }
|
---|
581 | index++;
|
---|
582 | }
|
---|
583 | }
|
---|
584 | }
|
---|
585 | }
|
---|
586 | }
|
---|
587 | else {
|
---|
588 | for (bf1=0; bf1<n1 ; bf1++) {
|
---|
589 | i2 = basis()->shell_to_function(s1) + bf1;
|
---|
590 |
|
---|
591 | for (bf2=0; bf2<n2 ; bf2++) {
|
---|
592 | j2 = basis()->shell_to_function(s2) + bf2;
|
---|
593 | if(i2>=j2) { i1=i2; j1=j2; }
|
---|
594 | else { i1=j2; j1=i2; }
|
---|
595 | ij1=ioff(i1)+j1;
|
---|
596 |
|
---|
597 | for (bf3=0; bf3<n3 ; bf3++) {
|
---|
598 | k2 = basis()->shell_to_function(s3) + bf3;
|
---|
599 |
|
---|
600 | for (bf4=0; bf4<n4; bf4++) {
|
---|
601 | if (fabs(mgdbuff[index])>1.0e-10) {
|
---|
602 | l2 = basis()->shell_to_function(s4) + bf4;
|
---|
603 |
|
---|
604 | if(k2>=l2) { k1=k2; l1=l2; }
|
---|
605 | else { k1=l2; l1=k2; }
|
---|
606 |
|
---|
607 | if(ij1 >= ioff(k1)+l1) {
|
---|
608 | ii = i1; jj = j1; kk = k1; ll = l1;
|
---|
609 | }
|
---|
610 | else {
|
---|
611 | ii = k1; jj = l1; kk = i1; ll = j1;
|
---|
612 | }
|
---|
613 |
|
---|
614 | pki_int = mgdbuff[index];
|
---|
615 |
|
---|
616 | if (jj == kk) {
|
---|
617 | lij=ioff(ii)+jj;
|
---|
618 | lkl=ioff(kk)+ll;
|
---|
619 | value=0.75*pki_int;
|
---|
620 | gtmp[lij] += ptmp[lkl]*value;
|
---|
621 | gtmp[lkl] += ptmp[lij]*value;
|
---|
622 |
|
---|
623 | lij=ioff(ii)+ll;
|
---|
624 | lkl=IOFF(kk,jj);
|
---|
625 | value=0.5*pki_int;
|
---|
626 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
627 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
628 | }
|
---|
629 | else if (ii == kk || jj == ll) {
|
---|
630 | lij=ioff(ii)+jj;
|
---|
631 | lkl=ioff(kk)+ll;
|
---|
632 | value=0.75*pki_int;
|
---|
633 | gtmp[lij] += ptmp[lkl]*value;
|
---|
634 | gtmp[lkl] += ptmp[lij]*value;
|
---|
635 |
|
---|
636 | lij=ioff(ii)+kk;
|
---|
637 | lkl=IOFF(jj,ll);
|
---|
638 | value=0.5*pki_int;
|
---|
639 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
640 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
641 | }
|
---|
642 | else {
|
---|
643 | lij=ioff(ii)+jj;
|
---|
644 | lkl=ioff(kk)+ll;
|
---|
645 | value=pki_int;
|
---|
646 | gtmp[lij] += ptmp[lkl]*value;
|
---|
647 | gtmp[lkl] += ptmp[lij]*value;
|
---|
648 |
|
---|
649 | lij=ioff(ii)+kk;
|
---|
650 | lkl=IOFF(jj,ll);
|
---|
651 | value*=0.25;
|
---|
652 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
653 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
654 |
|
---|
655 | lij=ioff(ii)+ll;
|
---|
656 | lkl=IOFF(kk,jj);
|
---|
657 | gtmp[lij] -= ptmp[lkl]*value;
|
---|
658 | gtmp[lkl] -= ptmp[lij]*value;
|
---|
659 | }
|
---|
660 | }
|
---|
661 | index++;
|
---|
662 | }
|
---|
663 | }
|
---|
664 | }
|
---|
665 | }
|
---|
666 | }
|
---|
667 | tnint += (double) (n1*n2*n3*n4);
|
---|
668 | kl++;
|
---|
669 | int_index++;
|
---|
670 | } // exit l loop
|
---|
671 | } // exit k loop
|
---|
672 | } // exit j loop
|
---|
673 | } // exit i loop
|
---|
674 |
|
---|
675 | // Sum up contributions to gtmp
|
---|
676 | msg_->sum(gtmp,nbatri,ptmp);
|
---|
677 |
|
---|
678 |
|
---|
679 | // Put gtmp back into Gmat
|
---|
680 | for (i=0; i<nbasis; i++) {
|
---|
681 | for (j=0; j<=i; j++) {
|
---|
682 | ij = i*(i+1)/2 + j;
|
---|
683 | Gmat->set_element(i,j,gtmp[ij]);
|
---|
684 | // Gmat->set_element(j,i,gtmp[ij]); don't do this - only lower triangle
|
---|
685 | }
|
---|
686 | }
|
---|
687 |
|
---|
688 |
|
---|
689 | // Free up memory
|
---|
690 | if (gtmp) free(gtmp);
|
---|
691 | if (maxp) free(maxp);
|
---|
692 | if (ptmp) free(ptmp);
|
---|
693 | if (shnfunc) free(shnfunc);
|
---|
694 |
|
---|
695 | return 0;
|
---|
696 | }
|
---|
697 |
|
---|
698 | ////////////////////////////////////////////////////////////////////////////
|
---|
699 |
|
---|
700 | // Local Variables:
|
---|
701 | // mode: c++
|
---|
702 | // c-file-style: "CLJ-CONDENSED"
|
---|
703 | // End:
|
---|