6
#include <libipv1/ip_lib.h>
7
#include <libiwl/iwl.h>
8
#include <libciomr/libciomr.h>
9
#include <libint/libint.h>
10
#include <libderiv/libderiv.h>
15
#include"taylor_fm_eval.h"
19
#include "deriv1_quartet_data.h"
20
#include "small_fns.h"
25
/*--- Various data structures ---*/
26
struct iwlbuf TPDM; /* IWL buffer for two-pdm matrix elements */
27
struct shell_pair *sp_ij, *sp_kl;
28
Libderiv_t Libderiv; /* Integrals library object */
30
double_array_t fjt_table; /* table of auxiliary function F_m(u) for each primitive combination */
33
int ij, kl, ik, jl, ijkl;
34
int ioffset, joffset, koffset, loffset;
40
register int i, j, k, l, m, ii, jj, kk, ll;
41
register int si, sj, sk, sl ;
42
register int sii, sjj, skk, sll, slll;
43
register int pi, pj, pk, pl ;
45
register int pii, pjj, pkk, pll ;
46
int switch_ij, switch_kl, switch_ijkl;
47
int center_i, center_j, center_k, center_l;
51
int max_cart_class_size;
53
int bf_i, bf_j, bf_k, bf_l, so_i, so_j, so_k, so_l, s;
54
int np_i, np_j, np_k, np_l;
55
int ni, nj, nk, nl, quartet_size;
57
int si_fao, sj_fao, sk_fao, sl_fao;
58
int sii_fao, sjj_fao, skk_fao, sll_fao;
59
int ao_i, imax, ao_j, jmax, ao_k, kmax, ao_l, lmax;
62
int iimax, jjmax, kkmax, llmax;
63
int irrep, npi_ij, npi_kl, npi_ik, npi_jl, ind_offset;
65
int num_prim_comb, p, max_num_prim_comb;
67
int buf_offset, buf_4offset, buf_size, last_buf;
68
int quartet_done, offset;
74
double **grad_te_local;
78
double **dens_i, **dens_j;
79
double ddax, dday, ddaz, ddbx, ddby, ddbz,
80
ddcx, ddcy, ddcz, dddx, dddy, dddz;
85
iwl_buf_init(&TPDM, IOUnits.itapG, 0.0, 1, 1);
88
buf_size = TPDM.inbuf;
90
init_Taylor_Fm_Eval(BasisSet.max_am*4-4+DERIV_LVL,UserOptions.cutoff);
92
init_fjt(BasisSet.max_am*4+DERIV_LVL);
93
init_fjt_table(&fjt_table);
97
max_cart_class_size = ioff[BasisSet.max_am]*ioff[BasisSet.max_am]*ioff[BasisSet.max_am]*ioff[BasisSet.max_am];
98
max_class_size = max_cart_class_size;
99
max_num_prim_comb = (BasisSet.max_num_prims*BasisSet.max_num_prims)*
100
(BasisSet.max_num_prims*BasisSet.max_num_prims);
101
init_libderiv1(&Libderiv,BasisSet.max_am-1,max_num_prim_comb,max_cart_class_size);
102
FourInd = init_array(max_cart_class_size);
104
grad_te_local = block_matrix(Molecule.num_atoms,3);
106
/*-------------------------------------------------
107
generate all unique shell quartets with ordering
108
suitable for building the PK-matrix
109
-------------------------------------------------*/
110
for (sii=0; sii<BasisSet.num_shells; sii++)
111
for (sjj=0; sjj<=sii; sjj++)
112
for (skk=0; skk<=sii; skk++)
113
for (sll=0; sll<= ((sii == skk) ? sjj : skk); sll++){
115
si = sii; sj = sjj; sk = skk; sl = sll;
117
/*--- Skip this quartet if all four centers are the same ---*/
118
if (BasisSet.shells[si].center == BasisSet.shells[sj].center &&
119
BasisSet.shells[si].center == BasisSet.shells[sk].center &&
120
BasisSet.shells[si].center == BasisSet.shells[sl].center) {
121
/*--- If reading in density - need to skip the appropriate block of that too ---*/
123
last_buf = TPDM.lastbuf;
126
if (buf_offset < buf_size) {
127
i = TPDM.labels[buf_4offset] - si_fao;
133
else if (!last_buf) {
134
iwl_buf_fetch(&TPDM);
137
last_buf = TPDM.lastbuf;
140
punt(fpo," The last TPDM quartet not marked\n");
142
} while (!quartet_done);
151
/* place in "ascending" angular mom-
152
my simple way of optimizing PHG recursion (VRR) */
153
/* these first two are good for the HRR */
154
if(BasisSet.shells[si].am < BasisSet.shells[sj].am){
160
if(BasisSet.shells[sk].am < BasisSet.shells[sl].am){
166
/* this should be /good/ for the VRR */
167
if(BasisSet.shells[si].am + BasisSet.shells[sj].am > BasisSet.shells[sk].am + BasisSet.shells[sl].am){
177
ni = ioff[BasisSet.shells[si].am];
178
nj = ioff[BasisSet.shells[sj].am];
179
nk = ioff[BasisSet.shells[sk].am];
180
nl = ioff[BasisSet.shells[sl].am];
181
quartet_size = ni*nj*nk*nl;
183
np_i = BasisSet.shells[si].n_prims;
184
np_j = BasisSet.shells[sj].n_prims;
185
np_k = BasisSet.shells[sk].n_prims;
186
np_l = BasisSet.shells[sl].n_prims;
188
orig_am[0] = BasisSet.shells[si].am-1;
189
orig_am[1] = BasisSet.shells[sj].am-1;
190
orig_am[2] = BasisSet.shells[sk].am-1;
191
orig_am[3] = BasisSet.shells[sl].am-1;
192
am = orig_am[0] + orig_am[1] + orig_am[2] + orig_am[3];
194
sp_ij = &(BasisSet.shell_pairs[si][sj]);
195
sp_kl = &(BasisSet.shell_pairs[sk][sl]);
197
Libderiv.AB[0] = sp_ij->AB[0];
198
Libderiv.AB[1] = sp_ij->AB[1];
199
Libderiv.AB[2] = sp_ij->AB[2];
200
Libderiv.CD[0] = sp_kl->AB[0];
201
Libderiv.CD[1] = sp_kl->AB[1];
202
Libderiv.CD[2] = sp_kl->AB[2];
204
AB2 = Libderiv.AB[0]*Libderiv.AB[0]+
205
Libderiv.AB[1]*Libderiv.AB[1]+
206
Libderiv.AB[2]*Libderiv.AB[2];
207
CD2 = Libderiv.CD[0]*Libderiv.CD[0]+
208
Libderiv.CD[1]*Libderiv.CD[1]+
209
Libderiv.CD[2]*Libderiv.CD[2];
211
/*-------------------------
212
Figure out the prefactor
213
-------------------------*/
219
if (si == sk && sj == sl || si == sl && sj == sk)
221
pfac *= 8.0; /*--- The factor of 8 needed for correlated densities ---*/
223
/*--- Compute data for primitive quartets here ---*/
225
for (pi = 0; pi < np_i; pi++) {
226
max_pj = (si == sj) ? pi+1 : np_j;
227
for (pj = 0; pj < max_pj; pj++) {
228
m = (1 + (si == sj && pi != pj));
229
for (pk = 0; pk < np_k; pk++) {
230
max_pl = (sk == sl) ? pk+1 : np_l;
231
for (pl = 0; pl < max_pl; pl++){
232
n = m * (1 + (sk == sl && pk != pl));
234
deriv1_quartet_data(&(Libderiv.PrimQuartet[num_prim_comb++]),
236
sp_ij, sp_kl, am, pi, pj, pk, pl, n*pfac);
238
deriv1_quartet_data(&(Libderiv.PrimQuartet[num_prim_comb++]),
239
&fjt_table, AB2, CD2,
240
sp_ij, sp_kl, am, pi, pj, pk, pl, n*pfac);
248
/*--- Read in a shell quartet from disk ---*/
249
memset(FourInd,0,sizeof(double)*quartet_size);
250
last_buf = TPDM.lastbuf;
252
sii_fao = BasisSet.shells[sii].fao-1;
253
sjj_fao = BasisSet.shells[sjj].fao-1;
254
skk_fao = BasisSet.shells[skk].fao-1;
255
sll_fao = BasisSet.shells[sll].fao-1;
257
if (buf_offset < buf_size) {
258
i = TPDM.labels[buf_4offset] - sii_fao;
260
j = TPDM.labels[buf_4offset+1] - sjj_fao;
261
k = TPDM.labels[buf_4offset+2] - skk_fao;
262
l = TPDM.labels[buf_4offset+3] - sll_fao;
281
offset = ((i*nj+j)*nk+k)*nl+l;
282
FourInd[offset] += TPDM.values[buf_offset]*
283
GTOs.bf_norm[orig_am[0]][i]*
284
GTOs.bf_norm[orig_am[1]][j]*
285
GTOs.bf_norm[orig_am[2]][k]*
286
GTOs.bf_norm[orig_am[3]][l];
293
else if (!last_buf) {
294
iwl_buf_fetch(&TPDM);
297
last_buf = TPDM.lastbuf;
300
punt("The last TPDM quartet not marked");
302
} while (!quartet_done);
304
build_deriv1_eri[orig_am[0]][orig_am[1]][orig_am[2]][orig_am[3]](&Libderiv,num_prim_comb);
306
center_i = BasisSet.shells[si].center-1;
307
center_j = BasisSet.shells[sj].center-1;
308
center_k = BasisSet.shells[sk].center-1;
309
center_l = BasisSet.shells[sl].center-1;
312
for(k=0;k<quartet_size;k++)
313
ddax += Libderiv.ABCD[0][k]*FourInd[k];
314
grad_te_local[center_i][0] += ddax;
317
for(k=0;k<quartet_size;k++)
318
dday += Libderiv.ABCD[1][k]*FourInd[k];
319
grad_te_local[center_i][1] += dday;
322
for(k=0;k<quartet_size;k++)
323
ddaz += Libderiv.ABCD[2][k]*FourInd[k];
324
grad_te_local[center_i][2] += ddaz;
327
for(k=0;k<quartet_size;k++)
328
ddbx += Libderiv.ABCD[3][k]*FourInd[k];
329
grad_te_local[center_j][0] += ddbx;
332
for(k=0;k<quartet_size;k++)
333
ddby += Libderiv.ABCD[4][k]*FourInd[k];
334
grad_te_local[center_j][1] += ddby;
337
for(k=0;k<quartet_size;k++)
338
ddbz += Libderiv.ABCD[5][k]*FourInd[k];
339
grad_te_local[center_j][2] += ddbz;*/
342
for(k=0;k<quartet_size;k++)
343
ddcx += Libderiv.ABCD[6][k]*FourInd[k];
344
grad_te_local[center_k][0] += ddcx;
347
for(k=0;k<quartet_size;k++)
348
ddcy += Libderiv.ABCD[7][k]*FourInd[k];
349
grad_te_local[center_k][1] += ddcy;
352
for(k=0;k<quartet_size;k++)
353
ddcz += Libderiv.ABCD[8][k]*FourInd[k];
354
grad_te_local[center_k][2] += ddcz;
357
for(k=0;k<quartet_size;k++)
358
dddx += Libderiv.ABCD[9][k]*FourInd[k];
359
grad_te_local[center_l][0] += dddx;
362
for(k=0;k<quartet_size;k++)
363
dddy += Libderiv.ABCD[10][k]*FourInd[k];
364
grad_te_local[center_l][1] += dddy;
367
for(k=0;k<quartet_size;k++)
368
dddz += Libderiv.ABCD[11][k]*FourInd[k];
369
grad_te_local[center_l][2] += dddz;
371
grad_te_local[center_j][0] -= ddax + ddcx + dddx;
372
grad_te_local[center_j][1] -= dday + ddcy + dddy;
373
grad_te_local[center_j][2] -= ddaz + ddcz + dddz;
376
if (UserOptions.print_lvl >= PRINT_TEDERIV)
377
print_atomvec("Two-electron contribution to the forces (a.u.)",grad_te_local);
379
for(i=0;i<Molecule.num_atoms;i++) {
380
Grad[i][0] += grad_te_local[i][0];
381
Grad[i][1] += grad_te_local[i][1];
382
Grad[i][2] += grad_te_local[i][2];
389
free_block(grad_te_local);
390
free_libderiv(&Libderiv);
392
free_Taylor_Fm_Eval();
394
free_fjt_table(&fjt_table);
397
iwl_buf_close(&TPDM,1);