3
\brief Enter brief description of file here
10
#include<libiwl/iwl.h>
11
#include<libciomr/libciomr.h>
12
#include<libint/libint.h>
13
#include<libr12/libr12.h>
19
#include"r12_quartet_data.h"
21
#include"norm_quartet.h"
25
namespace psi { namespace CINTS {
28
const double toler = UserOptions.cutoff;
30
/*--- ASCII file to print integrals ---*/
31
FILE *teout[NUM_TE_TYPES];
32
char teout_filename[] = "teout0.dat";
34
/*--- Various data structures ---*/
35
struct iwlbuf TEOUT[NUM_TE_TYPES-1]; /* IWL buffer for target integrals */
36
int itapTE[NUM_TE_TYPES-1];
37
struct coordinates ericent[4]; /* coordinates of centers A, B, C, and D */
38
struct tebuf *tot_data[NUM_TE_TYPES]; /* accum. for contracted integrals */
39
struct shell_pair *sp_ij, *sp_kl;
40
struct unique_shell_pair *usp_ij,*usp_kl;
42
double_array_t fjt_table;
44
static char *te_operator[] = { "1/r12", "r12", "[r12,T1]" };
45
int total_te_count[NUM_TE_TYPES] = {0, 0, 0, 0};
46
int ij, kl, ik, jl, ijkl;
47
int ioffset, joffset, koffset, loffset;
51
int n, num[NUM_TE_TYPES];
54
int pkblock_end_index = -1;
55
register int i, j, k, l, ii, jj, kk, ll;
56
register int si, sj, sk, sl ;
57
register int sii, sjj, skk, sll , slll;
58
register int pi, pj, pk, pl ;
59
register int pii, pjj, pkk, pll ;
60
int upk, num_unique_pk;
61
int usi_arr[3], usj_arr[3], usk_arr[3], usl_arr[3];
62
int *sj_arr, *sk_arr, *sl_arr;
63
int *sj_fbf_arr, *sk_fbf_arr, *sl_fbf_arr;
64
int usii,usjj,uskk,usll,usi,usj,usk,usl;
65
int stab_i,stab_j,stab_k,stab_l,stab_ij,stab_kl;
66
int *R_list, *S_list, *T_list;
68
int dcr_ij, dcr_kl, dcr_ijkl;
70
int num_unique_quartets;
72
int max_num_unique_quartets;
73
int max_num_prim_comb;
77
int max_cart_class_size;
79
int bf_i, bf_j, bf_k, bf_l, so_i, so_j, so_k, so_l, s;
80
int so_ii, so_jj, so_kk, so_ll;
81
int np_i, np_j, np_k, np_l;
85
int iimax, jjmax, kkmax, llmax;
86
int irrep, npi_ij, npi_kl, npi_ik, npi_jl, ind_offset;
90
double so_int[NUM_TE_TYPES];
92
double *data[NUM_TE_TYPES];
93
double *puream_data[NUM_TE_TYPES];
94
double **plist_data[NUM_TE_TYPES];
95
double pkblock_end_value = 0.0;
98
double ssss, ss_r12_ss;
104
for(te_type=0;te_type<NUM_TE_TYPES;te_type++) {
105
teout_filename[5] = te_type + '0';
106
teout[te_type] = fopen(teout_filename,"w");
109
itapTE[0] = IOUnits.itap33;
110
itapTE[1] = IOUnits.itapR12;
111
itapTE[2] = IOUnits.itapT1;
112
for(te_type=0;te_type<NUM_TE_TYPES-1;te_type++) {
113
iwl_buf_init(&TEOUT[te_type], itapTE[te_type], toler, 0, 0);
115
init_fjt(BasisSet.max_am*4);
119
/*-------------------------
120
Allocate data structures
121
-------------------------*/
122
max_cart_class_size = ioff[BasisSet.max_am]*
123
ioff[BasisSet.max_am]*
124
ioff[BasisSet.max_am]*
125
ioff[BasisSet.max_am];
126
max_num_unique_quartets = Symmetry.max_stab_index*Symmetry.max_stab_index*Symmetry.max_stab_index;
127
for(te_type=0;te_type<NUM_TE_TYPES;te_type++) {
128
tot_data[te_type] = (struct tebuf*) malloc(max_num_unique_quartets*max_cart_class_size*sizeof(struct tebuf));
129
memset(tot_data[te_type], 0, (max_num_unique_quartets*max_cart_class_size)*sizeof(struct tebuf));
131
if (BasisSet.puream) {
132
if (Symmetry.nirreps == 1) { /*--- allocate NUM_TE_TYPES scratch arrays for cart->puream transformation ---*/
133
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
134
puream_data[te_type] = (double *) malloc(sizeof(double)*
135
(BasisSet.max_am*2-1)*
136
ioff[BasisSet.max_am]*
137
ioff[BasisSet.max_am]*
138
ioff[BasisSet.max_am]);
141
puream_data[0] = (double *) malloc(sizeof(double)*
142
(BasisSet.max_am*2-1)*
143
ioff[BasisSet.max_am]*
144
ioff[BasisSet.max_am]*
145
ioff[BasisSet.max_am]);
146
for(te_type=1;te_type<NUM_TE_TYPES;te_type++)
147
puream_data[te_type] = puream_data[0];
150
sj_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
151
sk_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
152
sl_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
153
if (Symmetry.nirreps > 1) {
155
max_class_size = (2*BasisSet.max_am-1)*(2*BasisSet.max_am-1)*(2*BasisSet.max_am-1)*(2*BasisSet.max_am-1);
157
max_class_size = max_cart_class_size;
158
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
159
plist_data[te_type] = block_matrix(max_num_unique_quartets,max_class_size);
160
sj_fbf_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
161
sk_fbf_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
162
sl_fbf_arr = (int *)malloc(sizeof(int)*max_num_unique_quartets);
165
max_num_prim_comb = (BasisSet.max_num_prims*
166
BasisSet.max_num_prims)*
167
(BasisSet.max_num_prims*
168
BasisSet.max_num_prims);
169
UserOptions.memory -= init_libr12(&Libr12,BasisSet.max_am-1,max_num_prim_comb);
170
init_fjt_table(&fjt_table);
172
/*-------------------------------------------------
173
generate all unique shell quartets with ordering
174
suitable for building the PK-matrix
175
-------------------------------------------------*/
176
for (usii=0; usii<Symmetry.num_unique_shells; usii++)
177
for (usjj=0; usjj<=usii; usjj++)
178
for (uskk=0; uskk<=usjj; uskk++)
179
for (usll=0; usll<=uskk; usll++){
181
/*--- Decide what shell quartets out of (ij|kl), (ik|jl), and (il|jk) are unique ---*/
182
usi_arr[0] = usii; usj_arr[0] = usjj; usk_arr[0] = uskk; usl_arr[0] = usll;
183
if (usii == usjj && usii == uskk || usjj == uskk && usjj == usll)
185
else if (usii == uskk || usjj == usll) {
187
usi_arr[1] = usii; usj_arr[1] = uskk; usk_arr[1] = usjj; usl_arr[1] = usll;
189
else if (usjj == uskk) {
191
usi_arr[1] = usii; usj_arr[1] = usll; usk_arr[1] = usjj; usl_arr[1] = uskk;
193
else if (usii == usjj || uskk == usll) {
195
usi_arr[1] = usii; usj_arr[1] = uskk; usk_arr[1] = usjj; usl_arr[1] = usll;
199
usi_arr[1] = usii; usj_arr[1] = uskk; usk_arr[1] = usjj; usl_arr[1] = usll;
200
usi_arr[2] = usii; usj_arr[2] = usll; usk_arr[2] = usjj; usl_arr[2] = uskk;
203
for(upk=0;upk<num_unique_pk;upk++) {
204
/*--- For each combination of unique shells generate "petit list" of shells ---*/
205
usi = usi_arr[upk]; usj = usj_arr[upk]; usk = usk_arr[upk]; usl = usl_arr[upk];
207
/* place in "ascending" angular momentum order-
208
remember that [r12,T1] do not like it, I will have to worry about that later */
209
/* these first two are good for the HRR */
210
if(BasisSet.shells[Symmetry.us2s[usi]].am < BasisSet.shells[Symmetry.us2s[usj]].am){
215
if(BasisSet.shells[Symmetry.us2s[usk]].am < BasisSet.shells[Symmetry.us2s[usl]].am){
220
/* this should be /good/ for the VRR */
221
if(BasisSet.shells[Symmetry.us2s[usi]].am + BasisSet.shells[Symmetry.us2s[usj]].am >
222
BasisSet.shells[Symmetry.us2s[usk]].am + BasisSet.shells[Symmetry.us2s[usl]].am){
231
si = Symmetry.us2s[usi];
232
sjj = Symmetry.us2s[usj];
233
skk = Symmetry.us2s[usk];
234
sll = Symmetry.us2s[usl];
235
if (Symmetry.nirreps > 1) { /*--- Non-C1 symmetry case ---*/
236
/*--- Generate the petite list of shell quadruplets using DCD approach of Davidson ---*/
237
usp_ij = &(Symmetry.us_pairs[usi][usj]);
238
usp_kl = &(Symmetry.us_pairs[usk][usl]);
239
stab_i = Symmetry.atom_positions[BasisSet.shells[si].center-1];
240
stab_j = Symmetry.atom_positions[BasisSet.shells[sjj].center-1];
241
stab_k = Symmetry.atom_positions[BasisSet.shells[skk].center-1];
242
stab_l = Symmetry.atom_positions[BasisSet.shells[sll].center-1];
243
stab_ij = Symmetry.GnG[stab_i][stab_j];
244
stab_kl = Symmetry.GnG[stab_k][stab_l];
245
R_list = Symmetry.dcr[stab_i][stab_j];
246
S_list = Symmetry.dcr[stab_k][stab_l];
247
T_list = Symmetry.dcr[stab_ij][stab_kl];
248
lambda_T = Symmetry.nirreps/Symmetry.dcr_deg[stab_ij][stab_kl];
249
ni = (BasisSet.puream ? 2*BasisSet.shells[si].am - 1 : ioff[BasisSet.shells[si].am]);
250
nj = (BasisSet.puream ? 2*BasisSet.shells[sjj].am - 1 : ioff[BasisSet.shells[sjj].am]);
251
nk = (BasisSet.puream ? 2*BasisSet.shells[skk].am - 1 : ioff[BasisSet.shells[skk].am]);
252
nl = (BasisSet.puream ? 2*BasisSet.shells[sll].am - 1 : ioff[BasisSet.shells[sll].am]);
253
class_size = ni*nj*nk*nl;
255
memset(sj_arr,0,sizeof(int)*max_num_unique_quartets);
256
memset(sk_arr,0,sizeof(int)*max_num_unique_quartets);
257
memset(sl_arr,0,sizeof(int)*max_num_unique_quartets);
258
memset(sj_fbf_arr,0,sizeof(int)*max_num_unique_quartets);
259
memset(sk_fbf_arr,0,sizeof(int)*max_num_unique_quartets);
260
memset(sl_fbf_arr,0,sizeof(int)*max_num_unique_quartets);
262
for(dcr_ij=0;dcr_ij<Symmetry.dcr_dim[stab_i][stab_j];dcr_ij++){
264
sj = BasisSet.shells[sjj].trans_vec[R]-1;
265
for(dcr_ijkl=0;dcr_ijkl<Symmetry.dcr_dim[stab_ij][stab_kl];dcr_ijkl++){
266
T = T_list[dcr_ijkl];
267
sk = BasisSet.shells[skk].trans_vec[T]-1;
268
slll = BasisSet.shells[sll].trans_vec[T]-1;
269
for(dcr_kl=0;dcr_kl<Symmetry.dcr_dim[stab_k][stab_l];dcr_kl++) {
271
sl = BasisSet.shells[slll].trans_vec[S]-1;
273
total_am = BasisSet.shells[si].am+BasisSet.shells[sj].am+BasisSet.shells[sk].am+BasisSet.shells[sl].am;
274
/*-------------------------------------------------------------
275
Obviously redundant or zero cases should be eliminated here!
276
Right now only zero case is eliminated. Redundancies arising
277
in DCD approach when usi == usj etc. may be eliminated too
278
but lambda_T will have to be replaced by an array (it won't
279
the same for every shell quartet in petite list anymore).
280
-------------------------------------------------------------*/
282
(BasisSet.shells[si].center!=BasisSet.shells[sj].center)||
283
(BasisSet.shells[sj].center!=BasisSet.shells[sk].center)||
284
(BasisSet.shells[sk].center!=BasisSet.shells[sl].center)) {
288
sj_fbf_arr[count] = BasisSet.shells[sj].fbf-1;
289
sk_fbf_arr[count] = BasisSet.shells[sk].fbf-1;
290
sl_fbf_arr[count] = BasisSet.shells[sl].fbf-1;
295
} /* petite list is ready to be used */
296
num_unique_quartets = count;
298
else { /*--- C1 symmetry case ---*/
299
num_unique_quartets = 1;
303
ni = (BasisSet.puream ? 2*BasisSet.shells[usi].am - 1 : ioff[BasisSet.shells[usi].am]);
304
nj = (BasisSet.puream ? 2*BasisSet.shells[usj].am - 1 : ioff[BasisSet.shells[usj].am]);
305
nk = (BasisSet.puream ? 2*BasisSet.shells[usk].am - 1 : ioff[BasisSet.shells[usk].am]);
306
nl = (BasisSet.puream ? 2*BasisSet.shells[usl].am - 1 : ioff[BasisSet.shells[usl].am]);
307
ioffset = BasisSet.shells[usi].fbf - 1;
308
joffset = BasisSet.shells[usj].fbf - 1;
309
koffset = BasisSet.shells[usk].fbf - 1;
310
loffset = BasisSet.shells[usl].fbf - 1;
313
np_i = BasisSet.shells[si].n_prims;
314
np_j = BasisSet.shells[sjj].n_prims;
315
np_k = BasisSet.shells[skk].n_prims;
316
np_l = BasisSet.shells[sll].n_prims;
318
orig_am[0] = BasisSet.shells[si].am-1;
319
orig_am[1] = BasisSet.shells[sjj].am-1;
320
orig_am[2] = BasisSet.shells[skk].am-1;
321
orig_am[3] = BasisSet.shells[sll].am-1;
322
am = orig_am[0] + orig_am[1] + orig_am[2] + orig_am[3];
325
/*----------------------------------
326
Compute the nonredundant quartets
327
----------------------------------*/
328
for(plquartet=0;plquartet<num_unique_quartets;plquartet++) {
329
sj = sj_arr[plquartet];
330
sk = sk_arr[plquartet];
331
sl = sl_arr[plquartet];
333
sp_ij = &(BasisSet.shell_pairs[si][sj]);
334
sp_kl = &(BasisSet.shell_pairs[sk][sl]);
336
Libr12.ShellQuartet.AB[0] = sp_ij->AB[0];
337
Libr12.ShellQuartet.AB[1] = sp_ij->AB[1];
338
Libr12.ShellQuartet.AB[2] = sp_ij->AB[2];
339
Libr12.ShellQuartet.CD[0] = sp_kl->AB[0];
340
Libr12.ShellQuartet.CD[1] = sp_kl->AB[1];
341
Libr12.ShellQuartet.CD[2] = sp_kl->AB[2];
342
Libr12.ShellQuartet.AC[0] = Molecule.centers[BasisSet.shells[si].center-1].x-
343
Molecule.centers[BasisSet.shells[sk].center-1].x;
344
Libr12.ShellQuartet.AC[1] = Molecule.centers[BasisSet.shells[si].center-1].y-
345
Molecule.centers[BasisSet.shells[sk].center-1].y;
346
Libr12.ShellQuartet.AC[2] = Molecule.centers[BasisSet.shells[si].center-1].z-
347
Molecule.centers[BasisSet.shells[sk].center-1].z;
348
Libr12.ShellQuartet.ABdotAC = Libr12.ShellQuartet.AB[0]*Libr12.ShellQuartet.AC[0]+
349
Libr12.ShellQuartet.AB[1]*Libr12.ShellQuartet.AC[1]+
350
Libr12.ShellQuartet.AB[2]*Libr12.ShellQuartet.AC[2];
351
Libr12.ShellQuartet.CDdotCA = -1.0*(Libr12.ShellQuartet.CD[0]*Libr12.ShellQuartet.AC[0]+
352
Libr12.ShellQuartet.CD[1]*Libr12.ShellQuartet.AC[1]+
353
Libr12.ShellQuartet.CD[2]*Libr12.ShellQuartet.AC[2]);
354
AB2 = Libr12.ShellQuartet.AB[0]*Libr12.ShellQuartet.AB[0]+
355
Libr12.ShellQuartet.AB[1]*Libr12.ShellQuartet.AB[1]+
356
Libr12.ShellQuartet.AB[2]*Libr12.ShellQuartet.AB[2];
357
CD2 = Libr12.ShellQuartet.CD[0]*Libr12.ShellQuartet.CD[0]+
358
Libr12.ShellQuartet.CD[1]*Libr12.ShellQuartet.CD[1]+
359
Libr12.ShellQuartet.CD[2]*Libr12.ShellQuartet.CD[2];
361
/*--------------------------------
362
contract by primitives out here
363
--------------------------------*/
365
for (pi = 0; pi < np_i; pi++)
366
for (pj = 0; pj < np_j; pj++)
367
for (pk = 0; pk < np_k; pk++)
368
for (pl = 0; pl < np_l; pl++){
369
r12_quartet_data(&(Libr12.PrimQuartet[num_prim_comb++]), &fjt_table, AB2, CD2,
370
sp_ij, sp_kl, am, pi, pj, pk, pl, lambda_T);
375
build_r12_grt[orig_am[0]][orig_am[1]][orig_am[2]][orig_am[3]](&Libr12, num_prim_comb);
376
/*--- copy transformed data to plist_data to be used in the symmetrization step ---*/
377
if (Symmetry.nirreps > 1)
378
for(te_type=0;te_type<NUM_TE_TYPES;te_type++) {
379
data[te_type] = norm_quartet(Libr12.te_ptr[te_type], puream_data[te_type], orig_am, BasisSet.puream);
380
memcpy(plist_data[te_type][plquartet],data[te_type],sizeof(double)*class_size);
382
/*--- or just transform data ---*/
384
for(te_type=0;te_type<NUM_TE_TYPES;te_type++) {
385
data[te_type] = norm_quartet(Libr12.te_ptr[te_type], puream_data[te_type], orig_am, BasisSet.puream);
392
for(p=0;p<num_prim_comb;p++) {
393
ssss += Libr12.PrimQuartet[p].F[0];
394
ss_r12_ss += Libr12.PrimQuartet[p].ss_r12_ss;
396
build_r12_grt[0][0][0][0](&Libr12,num_prim_comb);
397
if (Symmetry.nirreps > 1) {
398
plist_data[0][plquartet][0] = ssss;
399
plist_data[1][plquartet][0] = ss_r12_ss;
400
plist_data[2][plquartet][0] = Libr12.te_ptr[2][0];
401
plist_data[3][plquartet][0] = Libr12.te_ptr[3][0];
404
/*--------------------------------------------------------
405
This was so freaking careless on my part. I forgot that
406
in hrr_grt_order_0000 te_ptr[2] and te_ptr[3] point to
407
int_stack[1] and int_stack[0] respectively. Therefore I
408
have to copy these into int_stack[2] and int_stack[3] first
409
before copying ssss and ss_r12_ss into those locations.
410
--------------------------------------------------------*/
411
Libr12.int_stack[2] = Libr12.te_ptr[2][0];
412
Libr12.int_stack[3] = Libr12.te_ptr[3][0];
413
Libr12.int_stack[0] = ssss;
414
Libr12.int_stack[1] = ss_r12_ss;
415
data[0] = Libr12.int_stack;
416
data[1] = Libr12.int_stack+1;
417
data[2] = Libr12.int_stack+2;
418
data[3] = Libr12.int_stack+3;
422
} /* end of computing "petit" list */
424
memset(num,0,NUM_TE_TYPES*sizeof(int));
425
if (Symmetry.nirreps > 1) { /*--- Non-C1 case ---*/
426
/*------------------------------------------------------------------------
427
Now we have everything to build SO's. Need to distinguish several cases
428
that are slightly different from each other. To avoid extra if's inside
429
the loops I separated them:
430
1) usi == usj == usk == usl
431
2) usi == usj != usk == usl
432
3) usi == usk != usj == usl
436
"Symmetrization" is based on Pitzer's equal contribution theorem.
438
The general procedure is as follows:
439
1) loop over irreps, if there are any SO products that arise from
440
this usp_ij pair and belong to this irrep, loop over them (ij)
441
2) from ij figure out product of which SOs this is, and what AOs
442
(or should I say, basis functions) contribute to these SO.
443
so_i and so_j are absolute indices, but i and j are relative
444
indices (i and j are indices of cart/puream components in usi
446
3) if there are any products of SOs from usp_kl that belong to irrep,
447
loop over those (kl). Obviously, the whole point of introducing
448
restrictions on different cases was to improve efficiency, but now
449
it seems like a stupid idea. I should have left just one loop case.
451
For more comments see Default_Ints/te_ints.c
452
------------------------------------------------------------------------*/
453
bf_i = BasisSet.shells[si].fbf-1;
454
if (usi == usj && usi == usk && usi == usl || usi == usk && usj == usl)
455
for(irrep=0;irrep<Symmetry.nirreps;irrep++) {
456
if (npi_ij = usp_ij->SOpair_npi[irrep])
457
for(ij=0;ij<npi_ij;ij++) {
458
so_i = usp_ij->SOpair_so_i[irrep][ij];
459
so_j = usp_ij->SOpair_so_j[irrep][ij];
460
i = usp_ij->SOpair_bf_i[irrep][ij];
461
j = usp_ij->SOpair_bf_j[irrep][ij];
462
ind_offset = (i*nj + j)*nk*nl;
463
for(kl=0;kl<=ij;kl++) {
464
so_k = usp_kl->SOpair_so_i[irrep][kl];
465
so_l = usp_kl->SOpair_so_j[irrep][kl];
466
k = usp_kl->SOpair_bf_i[irrep][kl];
467
l = usp_kl->SOpair_bf_j[irrep][kl];
468
index = ind_offset + k*nl + l;
469
memset(so_int,0,NUM_TE_TYPES*sizeof(double));
470
for(s=0;s<num_unique_quartets;s++){
472
bf_j = sj_fbf_arr[s]+j;
473
bf_k = sk_fbf_arr[s]+k;
474
bf_l = sl_fbf_arr[s]+l;
475
temp = Symmetry.usotao[so_i][ioffset]*
476
Symmetry.usotao[so_j][bf_j]*
477
Symmetry.usotao[so_k][bf_k]*
478
Symmetry.usotao[so_l][bf_l];
479
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
480
so_int[te_type] += temp*plist_data[te_type][s][index];
482
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
483
if (fabs(so_int[te_type])>toler) {
490
if (te_type == 2) /* [r12,T1] is antisymmetric WRT i and j */
491
so_int[te_type] *= -1.0;
495
if (te_type == 3) /* [r12,T2] is antisymmetric WRT to k and l */
496
so_int[te_type] *= -1.0;
498
if ((so_ii < so_kk) || (so_ii == so_kk && so_jj < so_ll)) {
499
if (te_type < 2) { /* only eri and r12 ints have bra-ket symmetry */
504
tot_data[te_type][num[te_type]].i = (short int) so_ii;
505
tot_data[te_type][num[te_type]].j = (short int) so_jj;
506
tot_data[te_type][num[te_type]].k = (short int) so_kk;
507
tot_data[te_type][num[te_type]].l = (short int) so_ll;
508
tot_data[te_type][num[te_type]].val = so_int[te_type];
515
for(irrep=0;irrep<Symmetry.nirreps;irrep++) {
516
if ((npi_ij = usp_ij->SOpair_npi[irrep]) && (npi_kl = usp_kl->SOpair_npi[irrep]))
517
for(ij=0;ij<npi_ij;ij++) {
518
i = usp_ij->SOpair_bf_i[irrep][ij];
519
j = usp_ij->SOpair_bf_j[irrep][ij];
520
so_i = usp_ij->SOpair_so_i[irrep][ij];
521
so_j = usp_ij->SOpair_so_j[irrep][ij];
522
ind_offset = (i*nj + j)*nk*nl;
523
for(kl=0;kl<npi_kl;kl++) {
524
k = usp_kl->SOpair_bf_i[irrep][kl];
525
l = usp_kl->SOpair_bf_j[irrep][kl];
526
so_k = usp_kl->SOpair_so_i[irrep][kl];
527
so_l = usp_kl->SOpair_so_j[irrep][kl];
528
index = ind_offset + k*nl + l;
529
memset(so_int,0,NUM_TE_TYPES*sizeof(double));
530
for(s=0;s<num_unique_quartets;s++){
532
bf_j = sj_fbf_arr[s]+j;
533
bf_k = sk_fbf_arr[s]+k;
534
bf_l = sl_fbf_arr[s]+l;
535
temp = Symmetry.usotao[so_i][ioffset]*
536
Symmetry.usotao[so_j][bf_j]*
537
Symmetry.usotao[so_k][bf_k]*
538
Symmetry.usotao[so_l][bf_l];
539
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
540
so_int[te_type] += temp*plist_data[te_type][s][index];
542
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
543
if (fabs(so_int[te_type])>toler) {
550
if (te_type == 2) /* [r12,T1] is antisymmetric WRT i and j */
551
so_int[te_type] *= -1.0;
555
if (te_type == 3) /* [r12,T2] is antisymmetric WRT to k and l */
556
so_int[te_type] *= -1.0;
558
if ((so_ii < so_kk) || (so_ii == so_kk && so_jj < so_ll)) {
559
if (te_type < 2) { /* only eri and r12 ints have bra-ket symmetry */
564
tot_data[te_type][num[te_type]].i = (short int) so_ii;
565
tot_data[te_type][num[te_type]].j = (short int) so_jj;
566
tot_data[te_type][num[te_type]].k = (short int) so_kk;
567
tot_data[te_type][num[te_type]].l = (short int) so_ll;
568
tot_data[te_type][num[te_type]].val = so_int[te_type];
575
else { /*--- C1 symmetry ---*/
576
/*--- Here just put non-redundant integrals to tot_data ---*/
577
if(usi==usj&&usk==usl&&usi==usk) { /*--- All shells are the same - the (aa|aa) case ---*/
579
for(ii=0; ii <= iimax; ii++){
581
for(jj=0; jj <= jjmax; jj++){
583
for(kk=0; kk <= kkmax; kk++){
584
llmax = (kk==ii)? jj : kk ;
585
for(ll=0; ll <= llmax; ll++){
586
index = ll+nl*(kk+nk*(jj+nj*ii));
587
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
588
if(fabs(data[te_type][index])>toler){
589
tot_data[te_type][num[te_type]].i = (short int) (ii+ioffset);
590
tot_data[te_type][num[te_type]].j = (short int) (jj+joffset);
591
tot_data[te_type][num[te_type]].k = (short int) (kk+koffset);
592
tot_data[te_type][num[te_type]].l = (short int) (ll+loffset);
593
tot_data[te_type][num[te_type]].val = data[te_type][index];
601
else if(usi==usk && usj==usl){ /*--- The (ab|ab) case ---*/
603
for(ii=0; ii <= iimax; ii++){
605
for(jj=0; jj <= jjmax; jj++){
607
for(kk=0; kk <= kkmax; kk++){
608
llmax = (kk==ii)? jj : nl - 1;
609
for(ll=0; ll <= llmax; ll++){
610
index = ll+nl*(kk+nk*(jj+nj*ii));
611
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
612
if(fabs(data[te_type][index])>toler){
617
value = data[te_type][index];
621
if (te_type > 1) /* [r12,Ti] are antisymmetric WRT to i -> j, k -> l */
625
if (te_type < 2) { /* only eri and r12 ints have bra-ket symmetry */
630
tot_data[te_type][num[te_type]].i = (short int) i;
631
tot_data[te_type][num[te_type]].j = (short int) j;
632
tot_data[te_type][num[te_type]].k = (short int) k;
633
tot_data[te_type][num[te_type]].l = (short int) l;
634
tot_data[te_type][num[te_type]].val = value;
642
else { /*--- The (ab|cd) case ---*/
645
for(ii=0; ii <= iimax; ii++){
646
jjmax = (usi==usj) ? ii : nj - 1;
647
for(jj=0; jj <= jjmax; jj++){
648
for(kk=0; kk <= kkmax; kk++){
649
llmax = (usk==usl) ? kk : nl - 1;
650
for(ll=0; ll <= llmax; ll++){
651
index = ll+nl*(kk+nk*(jj+nj*ii));
652
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
653
if(fabs(data[te_type][index])>toler){
658
value = data[te_type][index];
661
if (te_type == 2) /* [r12,T1] is antisymmetric WRT i and j */
666
if (te_type == 3) /* [r12,T2] is antisymmetric WRT k and l */
669
if ((i < k) || (i == k && j < l)) {
670
if (te_type < 2) { /* only eri and r12 ints have bra-ket symmetry */
675
tot_data[te_type][num[te_type]].i = (short int) i;
676
tot_data[te_type][num[te_type]].j = (short int) j;
677
tot_data[te_type][num[te_type]].k = (short int) k;
678
tot_data[te_type][num[te_type]].l = (short int) l;
679
tot_data[te_type][num[te_type]].val = value;
693
if (num[0]) { /* Let's see if we need to write out something */
694
total_te_count[0] += num[0];
695
if (upk == num_unique_pk - 1) /* if this is the last quartet needed for a pk-block - let CSCF know
696
by setting index i of the last integral to negative of itself.
697
The only guy where this trick won't work will be (00|00).
698
But normally (00|00) is of (ss|ss) type and is enough for computing one
699
pk-matrix element. PK-buffer won't get overfull because of this one guy */
700
tot_data[0][num[0]-1].i = -tot_data[0][num[0]-1].i;
701
iwl_buf_wrt_struct_nocut(&TEOUT[0], tot_data[0], num[0]);
707
if (num[1]) { /* Let's see if we need to write out something */
708
total_te_count[1] += num[1];
709
iwl_buf_wrt_struct_nocut(&TEOUT[1], tot_data[1], num[1]);
712
if (NUM_TE_TYPES > 2) {
713
/*---------------------
715
---------------------*/
716
if (num[2]) { /* Let's see if we need to write out something */
717
total_te_count[2] += num[2];
718
iwl_buf_wrt_struct_nocut(&TEOUT[2], tot_data[2], num[2]);
721
/*-----------------------------------
722
Convert [r12,T2]'s into [r12,T1]'s
723
-----------------------------------*/
724
for(i=0;i<num[3];i++)
725
if (tot_data[3][i].i == tot_data[3][i].k && tot_data[3][i].j == tot_data[3][i].l) {
726
/* Do NOT write out if ij == kl because (ij|[r12,T1]|ij) = (ij|[r12,T2]|ij) */
727
tot_data[3][i].val = 0.0;
732
SWAP(tot_data[3][i].i,tot_data[3][i].k);
733
SWAP(tot_data[3][i].j,tot_data[3][i].l);
735
if (num[3]) { /* Let's see if we need to write out something */
736
total_te_count[2] += num[3];
737
iwl_buf_wrt_struct(&TEOUT[2], tot_data[3], num[3], toler);
742
for(te_type=0;te_type<NUM_TE_TYPES;te_type++) {
744
for(n=0; n<num[te_type]; n++){
745
fprintf(teout[te_type], "%5d%5d%5d%5d%20.10lf\n",
746
abs(tot_data[te_type][n].i)+1,
747
tot_data[te_type][n].j+1,
748
tot_data[te_type][n].k+1,
749
tot_data[te_type][n].l+1,
750
tot_data[te_type][n].val);
752
fflush(teout[te_type]);
754
else { /* We've swapped ij and kl in [r12,T2] case, remember? */
755
for(n=0; n<num[te_type]; n++){
756
fprintf(teout[te_type], "%5d%5d%5d%5d%20.10lf\n",
757
tot_data[te_type][n].k+1,
758
tot_data[te_type][n].l+1,
759
tot_data[te_type][n].i+1,
760
tot_data[te_type][n].j+1,
761
tot_data[te_type][n].val);
763
fflush(teout[te_type]);
767
} /* end of computing PK-quartets. */
769
} /* end getting unique shell combination */
771
for(te_type=0;te_type<NUM_TE_TYPES-1;te_type++) {
772
iwl_buf_flush(&TEOUT[te_type], 1);
773
iwl_buf_close(&TEOUT[te_type], 1);
777
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
778
fclose(teout[te_type]);
782
for(te_type=0;te_type<NUM_TE_TYPES-1;te_type++)
783
fprintf(outfile," Wrote %d two-electron integrals of %s to IWL file %2d\n",
784
total_te_count[te_type],te_operator[te_type],itapTE[te_type]);
785
fprintf(outfile,"\n");
790
free_libr12(&Libr12);
791
free_fjt(&fjt_table);
792
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
793
free(tot_data[te_type]);
797
if (Symmetry.nirreps > 1) {
798
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
799
free_block(plist_data[te_type]);
804
if (BasisSet.puream) {
805
if (Symmetry.nirreps > 1)
806
free(puream_data[0]);
808
for(te_type=0;te_type<NUM_TE_TYPES;te_type++)
809
free(puream_data[te_type]);