~ubuntu-branches/ubuntu/quantal/psicode/quantal

« back to all changes in this revision

Viewing changes to src/bin/transqt/yoshimine.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck, Michael Banck, Daniel Leidert
  • Date: 2009-02-23 00:12:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090223001202-rutldoy3dimfpesc
Tags: 3.4.0-1
* New upstream release.

[ Michael Banck ]
* debian/patches/01_DESTDIR.dpatch: Refreshed.
* debian/patches/02_FHS.dpatch: Removed, applied upstream.
* debian/patches/03_debian_docdir: Likewise.
* debian/patches/04_man.dpatch: Likewise.
* debian/patches/06_466828_fix_gcc_43_ftbfs.dpatch: Likewise.
* debian/patches/07_464867_move_executables: Fixed and refreshed.
* debian/patches/00list: Adjusted.
* debian/control: Improved description.
* debian/patches-held: Removed.
* debian/rules (install/psi3): Do not ship the ruby bindings for now.

[ Daniel Leidert ]
* debian/rules: Fix txtdir via DEB_MAKE_INSTALL_TARGET.
* debian/patches/01_DESTDIR.dpatch: Refreshed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*! \file
 
2
    \ingroup TRANSQT
 
3
    \brief Enter brief description of file here 
 
4
*/
 
5
/*
 
6
** YOSHIMINE.C: Functions for the Yoshimine Sort Object
 
7
**
 
8
** David Sherrill
 
9
** Center for Computational Quantum Chemistry, UGA
 
10
** February 1995
 
11
**
 
12
** Made slightly more general to handle MP2 restricted transformations by
 
13
** Daniel Crawford
 
14
** September 1995
 
15
**
 
16
*/
 
17
 
 
18
#include <cstdio>
 
19
#include <cstdlib>
 
20
#include <cmath>
 
21
#include <cstring>
 
22
#include <libciomr/libciomr.h>
 
23
#include <libqt/qt.h>
 
24
#include <libiwl/iwl.h>
 
25
#include <psifiles.h>
 
26
#define YEXTERN
 
27
#include "yoshimine.h"
 
28
#include "MOInfo.h"
 
29
 
 
30
namespace psi { namespace transqt {
 
31
 
 
32
extern struct MOInfo moinfo;
 
33
 
 
34
#define MIN0(a,b) (((a)<(b)) ? (a) : (b))
 
35
#define MAX0(a,b) (((a)>(b)) ? (a) : (b))
 
36
#define INDEX(i,j) ((i>j) ? (ioff[(i)]+(j)) : (ioff[(j)]+(i)))
 
37
 
 
38
/*
 
39
** YOSH_INIT(): This function initializes a Yoshimine sort object.
 
40
**    The data is contained in a structure YBuff.
 
41
**
 
42
** Parameters:
 
43
**    YBuff          =  pointer to struct which will hold data for the object
 
44
**    bra_indices    =  the number of bra_index pairs for the two-electron
 
45
**                      integrals being sorted
 
46
**    ket_indices    =  the number of ket_index pairs for the two-electron
 
47
**                      integrals being sorted
 
48
**    maxcor         =  the core memory, in bytes
 
49
**    maxcord        =  the core memory, in doubles
 
50
**    max_buckets    =  the max number of buckets to use (may be limited due
 
51
**                      to the fact that each bucket requires a consecutively
 
52
**                      numbered binary temp file).
 
53
**    first_tmp_file =  the number of the first tmp file used in the 
 
54
**                      Yoshimine sort (e.g. 80 for file80).
 
55
**    cutoff         =  minimum value to be kept for any value during the sort
 
56
**    outfile        =  the text output file
 
57
**
 
58
** Returns: none
 
59
**
 
60
** Note:  bra_indices and ket_indices replace nbstri in an attempt to somewhat
 
61
** generalize the sort for four-index quantities which index pairs may or
 
62
** may not be canonicalizable, e.g. integrals of (ov|ov) type, as may be
 
63
** found in MP2 energy calculations...the first and second (or third and 
 
64
** fourth) indices are not necessarily interchangeable.  Additionally,
 
65
** this modification has the added benefit that it will work when the
 
66
** number of left and right basis functions are not equal (e.g., when
 
67
** one has half-backtransformed integrals of the type (ao ao | mo mo)
 
68
** where nbfao != nbfmo.
 
69
*/
 
70
void yosh_init(struct yoshimine *YBuff, unsigned bra_indices,
 
71
               unsigned ket_indices, long maxcor,
 
72
               long maxcord, const int max_buckets,
 
73
               unsigned int first_tmp_file, 
 
74
               double cutoff, FILE *outfile)
 
75
{
 
76
   unsigned long long int twoel_array_size;              /*--- Although on 32-bit systems one can only allocate 2GB arrays
 
77
                                                           in 1 process space, one can store much bigger integrals files on disk ---*/
 
78
   unsigned int nbuckets;
 
79
   int i, j, pq;
 
80
   unsigned long int bytes_per_bucket, free_bytes_per_bucket;
 
81
 
 
82
   YBuff->first_tmp_file = first_tmp_file;
 
83
   twoel_array_size = bra_indices; twoel_array_size *= ket_indices;
 
84
   YBuff->core_loads = (twoel_array_size - 1) / maxcord + 1 ;
 
85
   nbuckets = YBuff->core_loads ;
 
86
   YBuff->nbuckets = nbuckets;
 
87
   YBuff->cutoff = cutoff;
 
88
   YBuff->bra_indices = bra_indices;
 
89
   YBuff->ket_indices = ket_indices;
 
90
   if (nbuckets > max_buckets) {
 
91
      fprintf(stderr, "(yosh_init): maximum number of buckets exceeded\n") ;
 
92
      fprintf(outfile, "(yosh_init): maximum number of buckets exceeded\n") ;
 
93
      fprintf(outfile, "   wanted %d buckets\n", nbuckets) ;
 
94
      tstop(outfile) ;
 
95
      exit(PSI_RETURN_FAILURE) ;
 
96
      }
 
97
 
 
98
   /* if the number of pq does not divide evenly among the buckets, then
 
99
    * the last bucket will have the remainder of the pq's.
 
100
    */
 
101
   YBuff->pq_per_bucket = bra_indices / nbuckets ;
 
102
 
 
103
   if (nbuckets == 1) {
 
104
      bytes_per_bucket = ((unsigned long int) (4*sizeof(int) + sizeof(double))) *
 
105
       ((unsigned long int) twoel_array_size) + (unsigned long int) (sizeof(struct iwlbuf)
 
106
       + IWL_INTS_PER_BUF * (4*sizeof(Label) + sizeof(Value))); 
 
107
    if (bytes_per_bucket > (unsigned long int) (maxcor/nbuckets))
 
108
      bytes_per_bucket = (unsigned long int) (maxcor / nbuckets);
 
109
   }
 
110
   else
 
111
      bytes_per_bucket = (unsigned long int) (maxcor / nbuckets);
 
112
 
 
113
   free_bytes_per_bucket = bytes_per_bucket - 
 
114
     (unsigned long int) (sizeof(struct iwlbuf) + IWL_INTS_PER_BUF * (4*sizeof(Label) + sizeof(Value)));
 
115
   YBuff->bucketsize = free_bytes_per_bucket / (4 * sizeof(int) +
 
116
      sizeof(double)); 
 
117
   YBuff->buckets = (struct bucket *) malloc(nbuckets * sizeof(struct bucket));
 
118
   YBuff->bucket_for_pq = (int *) malloc (bra_indices * sizeof(int));
 
119
   for (i=0,pq=0; i<nbuckets; i++) {
 
120
      if (i != (nbuckets - 1)) {
 
121
         for (j=0; j<YBuff->pq_per_bucket; j++) 
 
122
            YBuff->bucket_for_pq[pq++] = i;
 
123
            }
 
124
      else for (pq=pq; pq<bra_indices; pq++) YBuff->bucket_for_pq[pq] = i;
 
125
      } 
 
126
 
 
127
   for (i=0,j=0; i<(nbuckets-1); i++) {
 
128
      YBuff->buckets[i].in_bucket = 0;
 
129
      YBuff->buckets[i].lo = j;
 
130
      YBuff->buckets[i].hi = YBuff->buckets[i].lo + YBuff->pq_per_bucket - 1;
 
131
      j += YBuff->pq_per_bucket;
 
132
      }
 
133
   YBuff->buckets[i].in_bucket = 0;
 
134
   YBuff->buckets[i].lo = j;
 
135
   YBuff->buckets[i].hi = bra_indices - 1;
 
136
}
 
137
 
 
138
/* YOSH_DONE(): Free allocated memory and reset all options for a
 
139
** given Yoshimine sorting structure.
 
140
*/
 
141
void yosh_done(struct yoshimine *YBuff)
 
142
{
 
143
  YBuff->core_loads = 0;
 
144
  YBuff->nbuckets = 0;
 
145
  free(YBuff->bucket_for_pq);
 
146
  YBuff->bucketsize = 0;
 
147
  free(YBuff->buckets);
 
148
  YBuff->first_tmp_file = 0;
 
149
  YBuff->pq_per_bucket = 0;
 
150
  YBuff->bra_indices = 0;
 
151
  YBuff->ket_indices = 0;
 
152
  YBuff->cutoff = 0;
 
153
}
 
154
 
 
155
void yosh_init_buckets(struct yoshimine *YBuff)
 
156
{
 
157
  int i;
 
158
  
 
159
   for (i=0; i<(YBuff->nbuckets); i++) {
 
160
      YBuff->buckets[i].p = init_int_array(YBuff->bucketsize);
 
161
      YBuff->buckets[i].q = init_int_array(YBuff->bucketsize);
 
162
      YBuff->buckets[i].r = init_int_array(YBuff->bucketsize);
 
163
      YBuff->buckets[i].s = init_int_array(YBuff->bucketsize);
 
164
      YBuff->buckets[i].val = init_array(YBuff->bucketsize);
 
165
      iwl_buf_init(&(YBuff->buckets[i].IWLBuf),YBuff->first_tmp_file+i,
 
166
                   YBuff->cutoff,0, 0);
 
167
      }
 
168
}
 
169
 
 
170
/*
 
171
** YOSH_PRINT(): Print out the Yoshimine structure
 
172
**
 
173
*/
 
174
void yosh_print(struct yoshimine *YBuff, FILE *outfile) 
 
175
{
 
176
   fprintf(outfile, " Yoshimine structure:\n");
 
177
   fprintf(outfile, "\tbra_indices  = %10d\n", YBuff->bra_indices);
 
178
   fprintf(outfile, "\tket_indices  = %10d\n", YBuff->ket_indices);
 
179
   fprintf(outfile, "\tbin size   = %10d\n", YBuff->bucketsize) ;
 
180
   fprintf(outfile, "\tbins       = %10d\n", YBuff->nbuckets) ;
 
181
   fprintf(outfile, "\tcore loads = %10d\n", YBuff->core_loads) ;
 
182
   fprintf(outfile, "\tpq/bin     = %10d\n", YBuff->pq_per_bucket) ;
 
183
   fprintf(outfile, "\tcutoff     = %10.2E\n", YBuff->cutoff) ;
 
184
}
 
185
 
 
186
 
 
187
/*
 
188
** YOSH_CLOSE_BUCKETS(): Close the temporary binary files used for the
 
189
** Yoshimine sort (not the final output file).
 
190
**
 
191
** Arguments:
 
192
**    YBuff   =  pointer to yoshimine object
 
193
**    erase   =  1 to erase tmp files, else 0
 
194
**
 
195
** Returns: none
 
196
**
 
197
** This function was formerly called yosh_close_tmp_files().
 
198
*/
 
199
void yosh_close_buckets(struct yoshimine *YBuff, int erase)
 
200
{
 
201
   int i;
 
202
 
 
203
   for (i=0; i<YBuff->nbuckets; i++) { /* close but keep */
 
204
      iwl_buf_close(&(YBuff->buckets[i].IWLBuf), !erase);
 
205
      free(YBuff->buckets[i].p);
 
206
      free(YBuff->buckets[i].q);
 
207
      free(YBuff->buckets[i].r);
 
208
      free(YBuff->buckets[i].s);
 
209
      free(YBuff->buckets[i].val);
 
210
      }
 
211
}
 
212
 
 
213
 
 
214
 
 
215
/*
 
216
** YOSH_RDTWO() : Read two-electron integrals from
 
217
**    file33 (in IWL format) and prepare them for Yoshimine sorting.
 
218
**
 
219
** Adapted from Ed Seidl's CSCF rdtwo.c routine
 
220
** David Sherrill 
 
221
** Center for Computational Quantum Chemistry, UGA
 
222
**
 
223
** Created 1993
 
224
** Modified February 1995 to use new Yoshimine data structure
 
225
** Modified March 1995 to use nsoff array instead of call to abs_orb()
 
226
**
 
227
** Arguments:
 
228
**   YBuff        = Yoshimine object pointer
 
229
**   itapERI      = unit number for two el. file (33)
 
230
**   num_so       = array of number of symm orbs in each irrep (for reindex)
 
231
**   nirreps      = number of irreps
 
232
**   ioff         = standard lexical index array
 
233
**   elbert       = 1 for Elbert ordering, 0 for canonical ordering
 
234
**   P            = frozen core density matrix (lower triangle)
 
235
**   Hc           = frozen core operator (lower triangle)
 
236
**   matrix       = 1 for all rs for given pq, 0 otherwise
 
237
**                  (for matrix multiplication algorithm)
 
238
**   del_tei_file = 1 to delete the tei file (33), 0 otherwise
 
239
**   printflag    = 1 for printing (for debugging only!) else 0
 
240
**   outfile      = file to print integrals to (if printflag is set)
 
241
*/
 
242
void yosh_rdtwo(struct yoshimine *YBuff, int itapERI, int del_tei_file, int *num_so,
 
243
      int nirreps, int *ioff, int elbert, int fzcflag, double *P, double *Hc,
 
244
      int matrix, int printflag, FILE *outfile)
 
245
 
246
  int ilsti, nbuf;
 
247
  int i, ij, kl, ijkl;
 
248
  int ior, ism, jor, jsm;
 
249
  int kor, ksm, lor, lsm;
 
250
  int iabs, jabs, kabs, labs ;
 
251
  int d2i ;
 
252
  double value;
 
253
  int *tmp;
 
254
  struct bucket *bptr ;
 
255
  long int tmpi;
 
256
  int whichbucket, lastflag = 0, firstfile;
 
257
  int *nsoff;
 
258
  int a,b,c,d,ab,cd,ad,bc,dum,found=0;
 
259
  int al[8], bl[8], cl[8], dl[8];
 
260
  int fi;
 
261
  struct iwlbuf ERIIN;
 
262
 
 
263
  if (printflag) {
 
264
    fprintf(outfile, "Yoshimine rdtwo routine entered\n");
 
265
    fprintf(outfile, "Two-electron integrals from file%d:\n",itapERI);
 
266
  }
 
267
 
 
268
  firstfile = YBuff->first_tmp_file;
 
269
 
 
270
  iwl_buf_init(&ERIIN,itapERI,0.0,1,1);
 
271
 
 
272
  nsoff = init_int_array(nirreps);
 
273
  nsoff[0] = 0;
 
274
  for (i=1; i<nirreps; i++) {
 
275
    nsoff[i] = nsoff[i-1] + num_so[i-1];
 
276
  }
 
277
 
 
278
  do {
 
279
    /* read a buffer full */
 
280
    ilsti = ERIIN.lastbuf;
 
281
    nbuf = ERIIN.inbuf;
 
282
 
 
283
    fi = 0;
 
284
    for (i=0; i < nbuf ; i++,tmp += 2) { /* do funky stuff to unpack ints */
 
285
      iabs = abs(ERIIN.labels[fi]);
 
286
      jabs = ERIIN.labels[fi+1];
 
287
      kabs = ERIIN.labels[fi+2];
 
288
      labs = ERIIN.labels[fi+3];
 
289
      value = ERIIN.values[i];
 
290
      fi += 4;
 
291
         
 
292
      /* calculate ijkl lexical index */
 
293
      ij = ioff[iabs] + jabs;
 
294
      kl = ioff[kabs] + labs;
 
295
      ijkl = ioff[ij] + kl;
 
296
 
 
297
      /* newly added March 1995: construct the frozen core operator */
 
298
      if (fzcflag) {
 
299
        a = al[0] = iabs;
 
300
        b = bl[0] = jabs;
 
301
        c = cl[0] = kabs;
 
302
        d = dl[0] = labs;
 
303
        ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
304
        cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
305
        bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
306
        ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
307
        Hc[cd] += 2.0 * P[ab] * value;
 
308
        if (b >= c) Hc[bc] -= P[ad] * value;
 
309
 
 
310
        a = al[1] = jabs;
 
311
        b = bl[1] = iabs;
 
312
        c = cl[1] = kabs;
 
313
        d = dl[1] = labs;
 
314
        if (!(a == al[0] && b == bl[0] && c == cl[0] && d == dl[0])) {
 
315
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
316
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
317
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
318
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
319
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
320
          if (b >= c) Hc[bc] -= P[ad] * value;
 
321
        } 
 
322
 
 
323
        a = al[2] = iabs;
 
324
        b = bl[2] = jabs;
 
325
        c = cl[2] = labs;
 
326
        d = dl[2] = kabs;
 
327
        for (dum=0, found=0; dum < 2 && !found; dum++) {
 
328
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
329
        }
 
330
        if (!found) {
 
331
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
332
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
333
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
334
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
335
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
336
          if (b >= c) Hc[bc] -= P[ad] * value;
 
337
        }
 
338
 
 
339
        a = al[3] = jabs;
 
340
        b = bl[3] = iabs;
 
341
        c = cl[3] = labs;
 
342
        d = dl[3] = kabs;
 
343
        for (dum=0, found=0; dum < 3 && !found; dum++) {
 
344
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
345
        }
 
346
        if (!found) {
 
347
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
348
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
349
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
350
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
351
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
352
          if (b >= c) Hc[bc] -= P[ad] * value;
 
353
        }
 
354
 
 
355
        a = al[4] = kabs;
 
356
        b = bl[4] = labs;
 
357
        c = cl[4] = iabs;
 
358
        d = dl[4] = jabs;
 
359
        for (dum=0, found=0; dum < 4 && !found; dum++) {
 
360
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
361
        }
 
362
        if (!found) {
 
363
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
364
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
365
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
366
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
367
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
368
          if (b >= c) Hc[bc] -= P[ad] * value;
 
369
        }
 
370
 
 
371
        a = al[5] = kabs;
 
372
        b = bl[5] = labs;
 
373
        c = cl[5] = jabs;
 
374
        d = dl[5] = iabs;
 
375
        for (dum=0, found=0; dum < 5 && !found; dum++) {
 
376
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
377
        }
 
378
        if (!found) {
 
379
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
380
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
381
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
382
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
383
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
384
          if (b >= c) Hc[bc] -= P[ad] * value;
 
385
        }
 
386
 
 
387
        a = al[6] = labs;
 
388
        b = bl[6] = kabs;
 
389
        c = cl[6] = iabs;
 
390
        d = dl[6] = jabs;
 
391
        for (dum=0, found=0; dum < 6 && !found; dum++) {
 
392
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
393
        }
 
394
        if (!found) {
 
395
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
396
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
397
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
398
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
399
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
400
          if (b >= c) Hc[bc] -= P[ad] * value;
 
401
        }
 
402
 
 
403
        a = al[7] = labs;
 
404
        b = bl[7] = kabs;
 
405
        c = cl[7] = jabs;
 
406
        d = dl[7] = iabs;
 
407
        for (dum=0, found=0; dum < 7 && !found; dum++) {
 
408
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
409
        }
 
410
        if (!found) {
 
411
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
412
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
413
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
414
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
415
          if (c >= d) Hc[cd] += 2.0 * P[ab] * value;
 
416
          if (b >= c) Hc[bc] -= P[ad] * value;
 
417
        }
 
418
      } /* end construction of frozen core operator */
 
419
 
 
420
      /* figure out what bucket to put it in, and do so 
 
421
       *
 
422
       * Elbert wants us to sort by the lower index (kl) 
 
423
       * i.e. for us, ij > kl (guaranteed in 33), but for them kl > ij 
 
424
       *
 
425
       */
 
426
 
 
427
      if (elbert) whichbucket = YBuff->bucket_for_pq[kl] ; 
 
428
      else whichbucket = YBuff->bucket_for_pq[ij] ;
 
429
 
 
430
      bptr = YBuff->buckets+whichbucket ;
 
431
      tmpi = (bptr->in_bucket)++ ;
 
432
 
 
433
      /* switch things around here for Elbert (k->p, l->q, i->r, j->s) */
 
434
      if (elbert) {
 
435
        bptr->p[tmpi] = kabs;
 
436
        bptr->q[tmpi] = labs;
 
437
        bptr->r[tmpi] = iabs;
 
438
        bptr->s[tmpi] = jabs;
 
439
      }
 
440
      else {
 
441
        bptr->p[tmpi] = iabs;
 
442
        bptr->q[tmpi] = jabs;
 
443
        bptr->r[tmpi] = kabs;
 
444
        bptr->s[tmpi] = labs;
 
445
      }
 
446
 
 
447
      bptr->val[tmpi] = value;
 
448
 
 
449
      if (printflag)
 
450
        fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
451
                iabs, jabs, kabs, labs, ijkl, value) ;
 
452
      if ((tmpi+1) == YBuff->bucketsize) { /* need to flush bucket to disk */
 
453
        flush_bucket(bptr, 0);
 
454
        bptr->in_bucket = 0;
 
455
      }
 
456
 
 
457
      if(matrix && ij != kl) {
 
458
        whichbucket = YBuff->bucket_for_pq[kl] ;
 
459
        bptr = YBuff->buckets+whichbucket ;
 
460
        tmpi = (bptr->in_bucket)++; 
 
461
        bptr->p[tmpi] = kabs;
 
462
        bptr->q[tmpi] = labs;
 
463
        bptr->r[tmpi] = iabs;
 
464
        bptr->s[tmpi] = jabs;
 
465
        bptr->val[tmpi] = value;
 
466
        if ((tmpi+1) == YBuff->bucketsize) {
 
467
          flush_bucket(bptr, 0);
 
468
          bptr->in_bucket = 0;
 
469
        }
 
470
      }
 
471
         
 
472
    }
 
473
    if (!ilsti)
 
474
      iwl_buf_fetch(&ERIIN);
 
475
  } while(!ilsti);
 
476
 
 
477
  /* flush partially filled buckets */
 
478
  /* Ok, after "matrix" was added above, we ran into the possibility of
 
479
   * flushing TWO buffers with the lastflag set.  This would be bad,
 
480
   * because the second buffer would never be read.  Therefore, I have
 
481
   * always passed a lastflag of 0 to flush_bucket() in the code above,
 
482
   * and now I flush all buckets here with lastflag set to 1.  There
 
483
   * is a small possibility that I will write a buffer of all zeroes.
 
484
   * This should not actually cause a problem, the way the iwl buf reads
 
485
   * currently work.  Make sure to be careful if rewriting iwl routines!
 
486
   */
 
487
  for (i=0; i<YBuff->nbuckets; i++) { 
 
488
    flush_bucket((YBuff->buckets)+i, 1);
 
489
  }      
 
490
 
 
491
  free(nsoff);
 
492
 
 
493
  iwl_buf_close(&ERIIN, !del_tei_file);
 
494
}
 
495
 
 
496
/*
 
497
** YOSH_RDTWO_UHF() : Read two-electron integrals from file33 (in IWL
 
498
** format) and prepare them for Yoshimine sorting.
 
499
**
 
500
** Arguments:
 
501
**   YBuff        = Yoshimine object pointer
 
502
**   itapERI      = unit number for two el. file (33)
 
503
**   num_so       = array of number of symm orbs in each irrep (for reindex)
 
504
**   nirreps      = number of irreps
 
505
**   ioff         = standard lexical index array
 
506
**   elbert       = 1 for Elbert ordering, 0 for canonical ordering
 
507
**   Pa           = alpha frozen core density matrix (lower triangle)
 
508
**   Pb           = beta frozen core density matrix (lower triangle)
 
509
**   Hca          = alpha frozen core operator (lower triangle)
 
510
**   Hcb          = beta frozen core operator (lower triangle)
 
511
**   matrix       = 1 for all rs for given pq, 0 otherwise
 
512
**                  (for matrix multiplication algorithm)
 
513
**   del_tei_file = 1 to delete the tei file (33), 0 otherwise
 
514
**   printflag    = 1 for printing (for debugging only!) else 0
 
515
**   outfile      = file to print integrals to (if printflag is set)
 
516
*/
 
517
void yosh_rdtwo_uhf(struct yoshimine *YBuff, int itapERI, int del_tei_file, int *num_so,
 
518
                    int nirreps, int *ioff, int elbert, int fzcflag, double *Pa, double *Pb, 
 
519
                    double *Hca, double *Hcb, int matrix, int printflag, FILE *outfile)
 
520
 
521
  int ilsti, nbuf;
 
522
  int i, ij, kl, ijkl;
 
523
  int ior, ism, jor, jsm;
 
524
  int kor, ksm, lor, lsm;
 
525
  int iabs, jabs, kabs, labs ;
 
526
  int d2i ;
 
527
  double value;
 
528
  int *tmp;
 
529
  struct bucket *bptr ;
 
530
  long int tmpi;
 
531
  int whichbucket, lastflag = 0, firstfile;
 
532
  int *nsoff;
 
533
  int a,b,c,d,ab,cd,ad,bc,dum,found=0;
 
534
  int al[8], bl[8], cl[8], dl[8];
 
535
  int fi;
 
536
  struct iwlbuf ERIIN;
 
537
 
 
538
  if (printflag) {
 
539
    fprintf(outfile, "Yoshimine rdtwo routine entered\n");
 
540
    fprintf(outfile, "Two-electron integrals from file%d:\n",itapERI);
 
541
  }
 
542
 
 
543
  firstfile = YBuff->first_tmp_file;
 
544
 
 
545
  iwl_buf_init(&ERIIN,itapERI,0.0,1,1);
 
546
 
 
547
  nsoff = init_int_array(nirreps);
 
548
  nsoff[0] = 0;
 
549
  for (i=1; i<nirreps; i++) {
 
550
    nsoff[i] = nsoff[i-1] + num_so[i-1];
 
551
  }
 
552
 
 
553
  do {
 
554
    /* read a buffer full */
 
555
    ilsti = ERIIN.lastbuf;
 
556
    nbuf = ERIIN.inbuf;
 
557
 
 
558
    fi = 0;
 
559
    for (i=0; i < nbuf ; i++,tmp += 2) { /* do funky stuff to unpack ints */
 
560
      iabs = abs(ERIIN.labels[fi]);
 
561
      jabs = ERIIN.labels[fi+1];
 
562
      kabs = ERIIN.labels[fi+2];
 
563
      labs = ERIIN.labels[fi+3];
 
564
      value = ERIIN.values[i];
 
565
      fi += 4;
 
566
         
 
567
      /* calculate ijkl lexical index */
 
568
      ij = ioff[iabs] + jabs;
 
569
      kl = ioff[kabs] + labs;
 
570
      ijkl = ioff[ij] + kl;
 
571
 
 
572
      /* construct the UHF frozen core operator */
 
573
      if (fzcflag) {
 
574
        a = al[0] = iabs;
 
575
        b = bl[0] = jabs;
 
576
        c = cl[0] = kabs;
 
577
        d = dl[0] = labs;
 
578
        ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
579
        cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
580
        bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
581
        ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
582
        Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
583
        Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
584
        if (b >= c) {
 
585
          Hca[bc] -= Pa[ad] * value;
 
586
          Hcb[bc] -= Pb[ad] * value;
 
587
        }
 
588
 
 
589
        a = al[1] = jabs;
 
590
        b = bl[1] = iabs;
 
591
        c = cl[1] = kabs;
 
592
        d = dl[1] = labs;
 
593
        if (!(a == al[0] && b == bl[0] && c == cl[0] && d == dl[0])) {
 
594
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
595
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
596
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
597
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
598
          if (c >= d) {
 
599
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
600
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
601
          }
 
602
          if (b >= c) {
 
603
            Hca[bc] -= Pa[ad] * value;
 
604
            Hcb[bc] -= Pb[ad] * value;
 
605
          } 
 
606
        }
 
607
 
 
608
        a = al[2] = iabs;
 
609
        b = bl[2] = jabs;
 
610
        c = cl[2] = labs;
 
611
        d = dl[2] = kabs;
 
612
        for (dum=0, found=0; dum < 2 && !found; dum++) {
 
613
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
614
        }
 
615
        if (!found) {
 
616
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
617
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
618
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
619
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
620
          if (c >= d) {
 
621
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
622
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
623
          }
 
624
          if (b >= c) {
 
625
            Hca[bc] -= Pa[ad] * value;
 
626
            Hcb[bc] -= Pb[ad] * value;
 
627
          } 
 
628
        }
 
629
 
 
630
        a = al[3] = jabs;
 
631
        b = bl[3] = iabs;
 
632
        c = cl[3] = labs;
 
633
        d = dl[3] = kabs;
 
634
        for (dum=0, found=0; dum < 3 && !found; dum++) {
 
635
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
636
        }
 
637
        if (!found) {
 
638
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
639
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
640
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
641
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
642
          if (c >= d) {
 
643
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
644
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
645
          }
 
646
          if (b >= c) {
 
647
            Hca[bc] -= Pa[ad] * value;
 
648
            Hcb[bc] -= Pb[ad] * value;
 
649
          } 
 
650
        }
 
651
 
 
652
        a = al[4] = kabs;
 
653
        b = bl[4] = labs;
 
654
        c = cl[4] = iabs;
 
655
        d = dl[4] = jabs;
 
656
        for (dum=0, found=0; dum < 4 && !found; dum++) {
 
657
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
658
        }
 
659
        if (!found) {
 
660
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
661
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
662
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
663
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
664
          if (c >= d) {
 
665
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
666
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
667
          }
 
668
          if (b >= c) {
 
669
            Hca[bc] -= Pa[ad] * value;
 
670
            Hcb[bc] -= Pb[ad] * value;
 
671
          } 
 
672
        }
 
673
 
 
674
        a = al[5] = kabs;
 
675
        b = bl[5] = labs;
 
676
        c = cl[5] = jabs;
 
677
        d = dl[5] = iabs;
 
678
        for (dum=0, found=0; dum < 5 && !found; dum++) {
 
679
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
680
        }
 
681
        if (!found) {
 
682
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
683
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
684
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
685
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
686
          if (c >= d) {
 
687
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
688
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
689
          }
 
690
          if (b >= c) {
 
691
            Hca[bc] -= Pa[ad] * value;
 
692
            Hcb[bc] -= Pb[ad] * value;
 
693
          } 
 
694
        }
 
695
 
 
696
        a = al[6] = labs;
 
697
        b = bl[6] = kabs;
 
698
        c = cl[6] = iabs;
 
699
        d = dl[6] = jabs;
 
700
        for (dum=0, found=0; dum < 6 && !found; dum++) {
 
701
          if (a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
702
        }
 
703
        if (!found) {
 
704
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
705
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
706
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
707
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
708
          if (c >= d) {
 
709
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
710
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
711
          }
 
712
          if (b >= c) {
 
713
            Hca[bc] -= Pa[ad] * value;
 
714
            Hcb[bc] -= Pb[ad] * value;
 
715
          } 
 
716
        }
 
717
 
 
718
        a = al[7] = labs;
 
719
        b = bl[7] = kabs;
 
720
        c = cl[7] = jabs;
 
721
        d = dl[7] = iabs;
 
722
        for (dum=0, found=0; dum < 7 && !found; dum++) {
 
723
          if(a==al[dum] && b==bl[dum] && c==cl[dum] && d==dl[dum]) found=1;
 
724
        }
 
725
        if (!found) {
 
726
          ab = ioff[MAX0(a,b)] + MIN0(a,b);
 
727
          cd = ioff[MAX0(c,d)] + MIN0(c,d);
 
728
          bc = ioff[MAX0(b,c)] + MIN0(b,c);
 
729
          ad = ioff[MAX0(a,d)] + MIN0(a,d);
 
730
          if (c >= d) {
 
731
            Hca[cd] += (Pa[ab] + Pb[ab]) * value;
 
732
            Hcb[cd] += (Pa[ab] + Pb[ab]) * value;
 
733
          }
 
734
          if (b >= c) {
 
735
            Hca[bc] -= Pa[ad] * value;
 
736
            Hcb[bc] -= Pb[ad] * value;
 
737
          } 
 
738
        }
 
739
      } /* end construction of frozen core operator */
 
740
 
 
741
      /* figure out what bucket to put it in, and do so 
 
742
       *
 
743
       * Elbert wants us to sort by the lower index (kl) 
 
744
       * i.e. for us, ij > kl (guaranteed in 33), but for them kl > ij 
 
745
       *
 
746
       */
 
747
 
 
748
      if (elbert) whichbucket = YBuff->bucket_for_pq[kl] ; 
 
749
      else whichbucket = YBuff->bucket_for_pq[ij] ;
 
750
 
 
751
      bptr = YBuff->buckets+whichbucket ;
 
752
      tmpi = (bptr->in_bucket)++ ;
 
753
 
 
754
      /* switch things around here for Elbert (k->p, l->q, i->r, j->s) */
 
755
      if (elbert) {
 
756
        bptr->p[tmpi] = kabs;
 
757
        bptr->q[tmpi] = labs;
 
758
        bptr->r[tmpi] = iabs;
 
759
        bptr->s[tmpi] = jabs;
 
760
      }
 
761
      else {
 
762
        bptr->p[tmpi] = iabs;
 
763
        bptr->q[tmpi] = jabs;
 
764
        bptr->r[tmpi] = kabs;
 
765
        bptr->s[tmpi] = labs;
 
766
      }
 
767
 
 
768
      bptr->val[tmpi] = value;
 
769
 
 
770
      if (printflag)
 
771
        fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
772
                iabs, jabs, kabs, labs, ijkl, value) ;
 
773
      if ((tmpi+1) == YBuff->bucketsize) { /* need to flush bucket to disk */
 
774
        flush_bucket(bptr, 0);
 
775
        bptr->in_bucket = 0;
 
776
      }
 
777
 
 
778
      if(matrix && ij != kl) {
 
779
        whichbucket = YBuff->bucket_for_pq[kl] ;
 
780
        bptr = YBuff->buckets+whichbucket ;
 
781
        tmpi = (bptr->in_bucket)++; 
 
782
        bptr->p[tmpi] = kabs;
 
783
        bptr->q[tmpi] = labs;
 
784
        bptr->r[tmpi] = iabs;
 
785
        bptr->s[tmpi] = jabs;
 
786
        bptr->val[tmpi] = value;
 
787
        if ((tmpi+1) == YBuff->bucketsize) {
 
788
          flush_bucket(bptr, 0);
 
789
          bptr->in_bucket = 0;
 
790
        }
 
791
      }
 
792
         
 
793
    }
 
794
    if (!ilsti)
 
795
      iwl_buf_fetch(&ERIIN);
 
796
  } while(!ilsti);
 
797
 
 
798
  /* flush partially filled buckets */
 
799
  /* Ok, after "matrix" was added above, we ran into the possibility of
 
800
   * flushing TWO buffers with the lastflag set.  This would be bad,
 
801
   * because the second buffer would never be read.  Therefore, I have
 
802
   * always passed a lastflag of 0 to flush_bucket() in the code above,
 
803
   * and now I flush all buckets here with lastflag set to 1.  There
 
804
   * is a small possibility that I will write a buffer of all zeroes.
 
805
   * This should not actually cause a problem, the way the iwl buf reads
 
806
   * currently work.  Make sure to be careful if rewriting iwl routines!
 
807
   */
 
808
  for (i=0; i<YBuff->nbuckets; i++) { 
 
809
    flush_bucket((YBuff->buckets)+i, 1);
 
810
  }      
 
811
 
 
812
  free(nsoff);
 
813
  iwl_buf_close(&ERIIN, !del_tei_file);
 
814
}
 
815
 
 
816
/*
 
817
** YOSH_RDTWO_BACKTR() : Read two-electron integrals from an IWL file and 
 
818
**    prepare them for Yoshimine sorting.   We have removed support for
 
819
**    Elbert loops and frozen core, since the former is not currently
 
820
**    being used and the latter should not apply to backtransforms.
 
821
**    The main issue is whether we need to symmetrize the twopdm, or
 
822
**    whether it has already been symmetrized.  We assume that it always
 
823
**    has the symmetry (pq|rs) = (rs|pq), but it may not have the other
 
824
**    left-pair and right-pair permutational symmetries (the CI twopdm
 
825
**    for example does not have this symmetry naturally).  The transform
 
826
**    needs this symmetry (as does the derivative program), so we will
 
827
**    enforce it here if the user specifies.  We currently assume that
 
828
**    the tpdm on disk has only unique (pq|rs) pairs, and so for our
 
829
**    purposes we need to generate (rs|pq) just like we do when reading
 
830
**    the AO integrals in the regular forwards transform.
 
831
**  
 
832
** Based on the YOSH_RDTWO34() function
 
833
** C. David Sherrill 
 
834
** Created August 1997
 
835
**
 
836
** Arguments:
 
837
**   YBuff        = Yoshimine object pointer
 
838
**   tei_file     = unit number for two-electron integrals
 
839
**   ioff         = standard lexical index array
 
840
**   symmetrize   = symmetrize the incoming 2pdm 
 
841
**   add_ref_pt   = Add the factors arising from a reference determinant
 
842
**                  (n.b. assumes lowest MO's occupied)
 
843
**   del_tei_file = 1 to delete the tei file, 0 otherwise
 
844
**   printflag    = 1 for printing (for debugging only!) else 0
 
845
**   outfile      = file to print integrals to (if printflag is set)
 
846
*/
 
847
void yosh_rdtwo_backtr(struct yoshimine *YBuff, int tei_file, int *ioff, 
 
848
                       int symmetrize, int add_ref_pt, int del_tei_file, 
 
849
                       int printflag, FILE *outfile)
 
850
 
851
  int i, ij, kl, ijkl;
 
852
  int iabs, jabs, kabs, labs;
 
853
  double value;
 
854
  struct bucket *bptr;
 
855
  int whichbucket, lastbuf, idx;
 
856
  long int tmpi;
 
857
  struct iwlbuf Inbuf;
 
858
  Value *valptr;
 
859
  Label *lblptr;
 
860
 
 
861
  if (printflag) {
 
862
    fprintf(outfile, "Yoshimine rdtwo_backtr routine entered\n");
 
863
    fprintf(outfile, "Two-particle density from file %d:\n", tei_file);
 
864
  }
 
865
 
 
866
  iwl_buf_init(&Inbuf, tei_file, YBuff->cutoff, 1, 0);
 
867
  lblptr = Inbuf.labels;
 
868
  valptr = Inbuf.values;
 
869
 
 
870
  do {
 
871
    iwl_buf_fetch(&Inbuf);
 
872
    lastbuf = Inbuf.lastbuf;
 
873
    for (idx=4*Inbuf.idx; Inbuf.idx < Inbuf.inbuf; Inbuf.idx++) {
 
874
      iabs = (int) lblptr[idx++];
 
875
      jabs = (int) lblptr[idx++];
 
876
      kabs = (int) lblptr[idx++];
 
877
      labs = (int) lblptr[idx++];
 
878
       
 
879
      iabs = moinfo.corr2pitz_nofzv[iabs];
 
880
      jabs = moinfo.corr2pitz_nofzv[jabs];
 
881
      kabs = moinfo.corr2pitz_nofzv[kabs];
 
882
      labs = moinfo.corr2pitz_nofzv[labs];
 
883
       
 
884
      value = valptr[Inbuf.idx];
 
885
      if (symmetrize) {
 
886
        if (iabs != jabs) value *= 0.5;
 
887
        if (kabs != labs) value *= 0.5;
 
888
      }
 
889
 
 
890
      /* calculate ijkl lexical index (make no i>=j assumptions for now) */
 
891
      ij = INDEX(iabs,jabs);
 
892
      kl = INDEX(kabs,labs);
 
893
      ijkl = INDEX(ij,kl);  /* ijkl needed only in the print routine */
 
894
 
 
895
      /* figure out what bucket to put it in, and do so */
 
896
       
 
897
      whichbucket = YBuff->bucket_for_pq[ij];
 
898
      bptr = YBuff->buckets+whichbucket;
 
899
      tmpi = (bptr->in_bucket)++;
 
900
      bptr->p[tmpi] = iabs;
 
901
      bptr->q[tmpi] = jabs;
 
902
      bptr->r[tmpi] = kabs;
 
903
      bptr->s[tmpi] = labs;
 
904
      bptr->val[tmpi] = value;
 
905
       
 
906
      if (printflag)
 
907
        fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
908
                iabs, jabs, kabs, labs, ijkl, value) ;
 
909
      if ((tmpi+1) == YBuff->bucketsize) { /* need to flush bucket to disk */
 
910
        flush_bucket(bptr, 0);
 
911
        bptr->in_bucket = 0;
 
912
      }
 
913
 
 
914
       
 
915
      /* this generates (kl|ij) from (ij|kl) if necessary and puts it out */
 
916
      /* anaglogous to the "matrix" option in yosh_rdtwo()              */
 
917
      if (iabs != kabs || jabs != labs) {
 
918
        whichbucket = YBuff->bucket_for_pq[kl];
 
919
        bptr = YBuff->buckets+whichbucket;
 
920
        tmpi = (bptr->in_bucket)++; 
 
921
        bptr->p[tmpi] = kabs;
 
922
        bptr->q[tmpi] = labs;
 
923
        bptr->r[tmpi] = iabs;
 
924
        bptr->s[tmpi] = jabs;
 
925
        bptr->val[tmpi] = value;
 
926
        if (printflag)
 
927
          fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
928
                  kabs, labs, iabs, jabs, ijkl, value) ;
 
929
        if ((tmpi+1) == YBuff->bucketsize) {
 
930
          flush_bucket(bptr, 0);
 
931
          bptr->in_bucket = 0;
 
932
        }
 
933
      }
 
934
 
 
935
    }
 
936
     
 
937
  } while(!lastbuf);
 
938
 
 
939
  /* now add in contributions from the reference determinant if requested */
 
940
  if (add_ref_pt) add_2pdm_ref_pt(YBuff, ioff, printflag, outfile);
 
941
 
 
942
  /* flush partially filled buckets */
 
943
  for (i=0; i<YBuff->nbuckets; i++) { 
 
944
    flush_bucket((YBuff->buckets)+i, 1);
 
945
  }      
 
946
   
 
947
  iwl_buf_close(&Inbuf, !del_tei_file); 
 
948
}
 
949
 
 
950
/*
 
951
** YOSH_RDTWO_BACKTR_UHF() : Read two-particle density elements from
 
952
** an IWL file and prepare them for Yoshimine sorting.  The sorted
 
953
** twopdm elements, G(pqrs), produced by this code have unique p-q and
 
954
** r-s combinations, but no pq-rs packing.  However, the input
 
955
** twopdm's may not have this same structure, so the boolean arguments
 
956
** swap_bk and symm_pq are used to correct this problem.  There are
 
957
** two circumstances to consider:
 
958
**
 
959
** (1) If the MO twopdm lacks pq-rs symmetry (e.g., the AB twopdm),
 
960
** its input file should include all rs for each pq.  The swap_bk flag
 
961
** should be set to "0" in this case so that no "extra" G(rs,pq)
 
962
** components are written to the sorting buffers.  If the input twopdm
 
963
** has pq-rs symmetry (e.g., the AA and BB twopdms), only unique pq-rs
 
964
** combinations should be included and the swap_bk flag should be set
 
965
** to "1".
 
966
**
 
967
** (2) If the MO density lacks p-q and r-s symmetry, the input file
 
968
** should include all combinations of p,q and r,s, and the symm_pq
 
969
** flag should be set to "1".  If the MO density has p-q and r-s
 
970
** symmetry, then its input file should include only unique p,q and
 
971
** r,s combinations, and the symm_pq flag should be set to "0".
 
972
**
 
973
** Note that "intermediate" symmetry cases, where the MO twopdm has
 
974
** p-q symmetry but not r-s symmetry, for example, are not included
 
975
** here.
 
976
**
 
977
** Also, this code assumes the input indices are in QTS ordering and
 
978
** converts them automatically to Pitzer.
 
979
**
 
980
** TDC, 1/03
 
981
**  
 
982
** Based on the YOSH_RDTWO_BACKTR() function above by
 
983
** C. David Sherrill 
 
984
**
 
985
** Arguments:
 
986
**   YBuff        = Yoshimine object pointer
 
987
**   tei_file     = unit number for two-electron integrals
 
988
**   ioff         = standard lexical index array
 
989
**   swap_bk      = sort both G(pq,rs) and G(rs,pq) combinations
 
990
**   symm_pq      = symmetrize both p,q and r,s combinations
 
991
**   del_tei_file = 1 to delete the tei file, 0 otherwise
 
992
**   printflag    = 1 for printing (for debugging only!) else 0
 
993
**   outfile      = file to print integrals to (if printflag is set)
 
994
*/
 
995
void yosh_rdtwo_backtr_uhf(const char *spin, struct yoshimine *YBuff, int tei_file, int *ioff, 
 
996
                           int swap_bk, int symm_pq, int del_tei_file,
 
997
                           int printflag, FILE *outfile)
 
998
 
999
  int i, ij, kl, ijkl;
 
1000
  int iabs, jabs, kabs, labs;
 
1001
  double value;
 
1002
  struct bucket *bptr;
 
1003
  int whichbucket, lastbuf, idx;
 
1004
  long int tmpi;
 
1005
  struct iwlbuf Inbuf;
 
1006
  Value *valptr;
 
1007
  Label *lblptr;
 
1008
  int *iorder, *jorder, *korder, *lorder;
 
1009
 
 
1010
  if (printflag) {
 
1011
    fprintf(outfile, "Yoshimine rdtwo_backtr routine entered\n");
 
1012
    fprintf(outfile, "Two-particle density from file %d:\n", tei_file);
 
1013
  }
 
1014
 
 
1015
  if(!strcmp(spin, "AA")) {
 
1016
    iorder = moinfo.corr2pitz_nofzv_a;
 
1017
    jorder = moinfo.corr2pitz_nofzv_a;
 
1018
    korder = moinfo.corr2pitz_nofzv_a;
 
1019
    lorder = moinfo.corr2pitz_nofzv_a;
 
1020
  }
 
1021
  else if(!strcmp(spin, "BB")) {
 
1022
    iorder = moinfo.corr2pitz_nofzv_b;
 
1023
    jorder = moinfo.corr2pitz_nofzv_b;
 
1024
    korder = moinfo.corr2pitz_nofzv_b;
 
1025
    lorder = moinfo.corr2pitz_nofzv_b;
 
1026
  }
 
1027
  else if(!strcmp(spin, "AB")) {
 
1028
    iorder = moinfo.corr2pitz_nofzv_a;
 
1029
    jorder = moinfo.corr2pitz_nofzv_a;
 
1030
    korder = moinfo.corr2pitz_nofzv_b;
 
1031
    lorder = moinfo.corr2pitz_nofzv_b;
 
1032
  }
 
1033
  else {
 
1034
    fprintf(outfile, "\n\tInvalid spin cases requested for backtransformation!\n");
 
1035
    exit(PSI_RETURN_FAILURE);
 
1036
  }
 
1037
 
 
1038
  iwl_buf_init(&Inbuf, tei_file, YBuff->cutoff, 1, 0);
 
1039
  lblptr = Inbuf.labels;
 
1040
  valptr = Inbuf.values;
 
1041
 
 
1042
  do {
 
1043
    iwl_buf_fetch(&Inbuf);
 
1044
    lastbuf = Inbuf.lastbuf;
 
1045
    for (idx=4*Inbuf.idx; Inbuf.idx < Inbuf.inbuf; Inbuf.idx++) {
 
1046
      iabs = (int) lblptr[idx++];
 
1047
      jabs = (int) lblptr[idx++];
 
1048
      kabs = (int) lblptr[idx++];
 
1049
      labs = (int) lblptr[idx++];
 
1050
 
 
1051
      iabs = iorder[iabs];
 
1052
      jabs = jorder[jabs];
 
1053
      kabs = korder[kabs];
 
1054
      labs = lorder[labs];
 
1055
       
 
1056
      value = valptr[Inbuf.idx];
 
1057
 
 
1058
      if (symm_pq) {
 
1059
        if (iabs != jabs) value *= 0.5;
 
1060
        if (kabs != labs) value *= 0.5;
 
1061
      }
 
1062
 
 
1063
      /* calculate ijkl lexical index (make no i>=j assumptions for now) */
 
1064
      ij = INDEX(iabs,jabs);
 
1065
      kl = INDEX(kabs,labs);
 
1066
      ijkl = INDEX(ij,kl);  /* ijkl needed only in the print routine */
 
1067
 
 
1068
      /* figure out what bucket to put it in, and do so */
 
1069
       
 
1070
      whichbucket = YBuff->bucket_for_pq[ij];
 
1071
      bptr = YBuff->buckets+whichbucket;
 
1072
      tmpi = (bptr->in_bucket)++;
 
1073
      bptr->p[tmpi] = iabs;
 
1074
      bptr->q[tmpi] = jabs;
 
1075
      bptr->r[tmpi] = kabs;
 
1076
      bptr->s[tmpi] = labs;
 
1077
      bptr->val[tmpi] = value;
 
1078
       
 
1079
      if (printflag)
 
1080
        fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
1081
                iabs, jabs, kabs, labs, ijkl, value) ;
 
1082
      if ((tmpi+1) == YBuff->bucketsize) { /* need to flush bucket to disk */
 
1083
        flush_bucket(bptr, 0);
 
1084
        bptr->in_bucket = 0;
 
1085
      }
 
1086
 
 
1087
      /* this generates (kl|ij) from (ij|kl) if necessary and puts it out */
 
1088
      /* anaglogous to the "matrix" option in yosh_rdtwo()              */
 
1089
      if (swap_bk && (iabs != kabs || jabs != labs)) {
 
1090
        whichbucket = YBuff->bucket_for_pq[kl];
 
1091
        bptr = YBuff->buckets+whichbucket;
 
1092
        tmpi = (bptr->in_bucket)++; 
 
1093
        bptr->p[tmpi] = kabs;
 
1094
        bptr->q[tmpi] = labs;
 
1095
        bptr->r[tmpi] = iabs;
 
1096
        bptr->s[tmpi] = jabs;
 
1097
        bptr->val[tmpi] = value;
 
1098
        if (printflag)
 
1099
          fprintf(outfile, "%4d %4d %4d %4d  %4d   %10.6lf\n", 
 
1100
                  kabs, labs, iabs, jabs, ijkl, value) ;
 
1101
        if ((tmpi+1) == YBuff->bucketsize) {
 
1102
          flush_bucket(bptr, 0);
 
1103
          bptr->in_bucket = 0;
 
1104
        }
 
1105
      }
 
1106
 
 
1107
    }
 
1108
     
 
1109
  } while(!lastbuf);
 
1110
 
 
1111
  /* flush partially filled buckets */
 
1112
  for (i=0; i<YBuff->nbuckets; i++) { 
 
1113
    flush_bucket((YBuff->buckets)+i, 1);
 
1114
  }      
 
1115
   
 
1116
  iwl_buf_close(&Inbuf, !del_tei_file); 
 
1117
}
 
1118
 
 
1119
/*
 
1120
** ADD_2PDM_REF_PT
 
1121
**
 
1122
** This function adds in the contributions to the two-particle density
 
1123
** matrix from the reference determinant, as might be required in MBPT
 
1124
** or CC theory.  Assume the reference is made up of the lowest-lying
 
1125
** orbitals as specified by DOCC and SOCC arrays.  Assume restricted
 
1126
** orbitals.   Assume correlated ordering is docc, socc, virt...may
 
1127
** not always be true, but order array is already wiped out by this
 
1128
** point for backtransforms, would have to fetch it again.
 
1129
**
 
1130
** David Sherrill, Feb 1998
 
1131
*/
 
1132
void add_2pdm_ref_pt(struct yoshimine *YBuff, int *ioff, int pflg, 
 
1133
                     FILE *outfile)
 
1134
{
 
1135
   int i, j, ii, jj, ij;
 
1136
   int iabs, jabs;
 
1137
   int ndocc, nsocc;
 
1138
 
 
1139
   ndocc = moinfo.ndocc;  nsocc = moinfo.nsocc;
 
1140
 
 
1141
   /* closed-shell part */
 
1142
   for (i=0; i<ndocc; i++) {
 
1143
     iabs = moinfo.corr2pitz_nofzv[i];
 
1144
     ii = ioff[iabs] + iabs;
 
1145
 
 
1146
     for (j=0; j<i; j++) {
 
1147
       jabs = moinfo.corr2pitz_nofzv[j];
 
1148
       jj = ioff[jabs] + jabs;
 
1149
       ij = ioff[iabs] + jabs; 
 
1150
 
 
1151
       yosh_buff_put_val(YBuff,ioff,ii,iabs,iabs,jabs,jabs, 2.0,pflg,outfile);
 
1152
       yosh_buff_put_val(YBuff,ioff,jj,jabs,jabs,iabs,iabs, 2.0,pflg,outfile);
 
1153
       yosh_buff_put_val(YBuff,ioff,ij,iabs,jabs,jabs,iabs,-0.25,pflg,outfile);
 
1154
       yosh_buff_put_val(YBuff,ioff,ij,jabs,iabs,iabs,jabs,-0.25,pflg,outfile);
 
1155
 
 
1156
     }
 
1157
 
 
1158
     jabs = moinfo.corr2pitz_nofzv[j];
 
1159
     jj = ioff[jabs] + jabs;
 
1160
     ij = ioff[iabs] + jabs; 
 
1161
     yosh_buff_put_val(YBuff,ioff,ii,iabs,iabs,jabs,jabs, 1.0,pflg,outfile);
 
1162
  
 
1163
   }
 
1164
 
 
1165
 
 
1166
   /* open-shell part, if any */
 
1167
   for (i=ndocc; i<ndocc+nsocc; i++) {
 
1168
     iabs = moinfo.corr2pitz_nofzv[i];
 
1169
     ii = ioff[iabs] + iabs;
 
1170
 
 
1171
     for (j=0; j<ndocc; j++) {
 
1172
       jabs = moinfo.corr2pitz_nofzv[j];
 
1173
       jj = ioff[jabs] + jabs;
 
1174
       ij = ioff[iabs] + jabs;
 
1175
 
 
1176
       yosh_buff_put_val(YBuff,ioff,ii,iabs,iabs,jabs,jabs, 1.0,pflg,outfile);
 
1177
       yosh_buff_put_val(YBuff,ioff,jj,jabs,jabs,iabs,iabs, 1.0,pflg,outfile);
 
1178
       yosh_buff_put_val(YBuff,ioff,ij,iabs,jabs,jabs,iabs,-0.125,pflg,outfile);
 
1179
       yosh_buff_put_val(YBuff,ioff,ij,jabs,iabs,iabs,jabs,-0.125,pflg,outfile);
 
1180
     } 
 
1181
 
 
1182
     for (j=ndocc; j<i; j++) {
 
1183
       jabs = moinfo.corr2pitz_nofzv[j];
 
1184
       jj = ioff[jabs] + jabs;
 
1185
       ij = ioff[iabs] + jabs;
 
1186
 
 
1187
       yosh_buff_put_val(YBuff,ioff,ii,iabs,iabs,jabs,jabs, 0.5,pflg,outfile);
 
1188
       yosh_buff_put_val(YBuff,ioff,jj,jabs,jabs,iabs,iabs, 0.5,pflg,outfile);
 
1189
       yosh_buff_put_val(YBuff,ioff,ij,iabs,jabs,jabs,iabs,-0.125,pflg,outfile);
 
1190
       yosh_buff_put_val(YBuff,ioff,ij,jabs,iabs,iabs,jabs,-0.125,pflg,outfile);
 
1191
     }
 
1192
 
 
1193
   }
 
1194
 
 
1195
}
 
1196
 
 
1197
 
 
1198
 
 
1199
/*
 
1200
** YOSH_BUFF_PUT_VAL
 
1201
**
 
1202
** This function puts a value and its associated indices to a yoshimine
 
1203
** sorting buffer.
 
1204
*/
 
1205
void yosh_buff_put_val(struct yoshimine *YBuff, int *ioff, int pq, 
 
1206
                       int p, int q, int r, int s, double value, int prtflg,
 
1207
                       FILE *outfile)
 
1208
{
 
1209
   struct bucket *bptr;
 
1210
   int whichbucket;
 
1211
   long int tmpi;
 
1212
 
 
1213
   whichbucket = YBuff->bucket_for_pq[pq];
 
1214
   bptr = YBuff->buckets+whichbucket;
 
1215
   tmpi = (bptr->in_bucket)++; 
 
1216
   bptr->p[tmpi] = p;
 
1217
   bptr->q[tmpi] = q;
 
1218
   bptr->r[tmpi] = r;
 
1219
   bptr->s[tmpi] = s;
 
1220
   bptr->val[tmpi] = value;
 
1221
 
 
1222
   if (prtflg)
 
1223
     fprintf(outfile, "%4d %4d %4d %4d         %10.6lf\n", p, q, r, s,
 
1224
             value); 
 
1225
 
 
1226
   if ((tmpi+1) == YBuff->bucketsize) { /* need to flush bucket to disk */
 
1227
     flush_bucket(bptr, 0);
 
1228
     bptr->in_bucket = 0;
 
1229
   }
 
1230
 
 
1231
 
 
1232
}
 
1233
 
 
1234
 
 
1235
 
 
1236
/*
 
1237
** YOSH_SORT(): Sort all the buckets in the Yoshimine sorting algorithm.
 
1238
**    The call to sortbuf() will cause the intermediate files to be 
 
1239
**    deleted unless keep_bins is set to 1.
 
1240
**
 
1241
** Arguments:
 
1242
**    YBuff        =  pointer to Yoshimine object
 
1243
**    out_tape     =  number for binary output file 
 
1244
**    keep_bins    =  keep the intermediate tmp files
 
1245
**    ioff         =  the usual offset array unless no_pq_perm, in which 
 
1246
**                    case it is appropriate for the left indices, i.e., 
 
1247
**                    pq = ioff[p] + q
 
1248
**    ioff2        =  the Elbert ioff2 array if elbert=true.  If no_pq_perm,
 
1249
**                    then this is the usual ioff array, appropriate 
 
1250
**                    for the right indices
 
1251
**    nbfso        =  number of basis fns in symmetry orbitals
 
1252
**    ket_indices  =  number of ket indices (usually ntri) 
 
1253
**    elbert       =  are inputs in Elbert ordering? p>=q, r>=s, rs>=pq
 
1254
**    intermediate =  1 if sorting an intermediate in the transformation
 
1255
**                    (argument to sortbuf()).  This implies that the full
 
1256
**                    set of rs are available for a given pq.
 
1257
**    no_pq_perm   =  if p and q are not interchangeable (e.g., one is
 
1258
**                    occupied and one is virtual, as in MP2) 
 
1259
**    qdim         =  the number of possible values for index q 
 
1260
**    add          =  do additions of integrals during the sort? 
 
1261
**    print_lvl    =  verbosity level (how much to print)
 
1262
**    outfile      =  text output file
 
1263
**
 
1264
** Returns: none
 
1265
*/
 
1266
void yosh_sort(struct yoshimine *YBuff, int out_tape, int keep_bins,
 
1267
      int *ioff, int *ioff2, int nbfso, int ket_indices, int elbert, 
 
1268
      int intermediate, int no_pq_perm, int qdim, int add, int print_lvl, 
 
1269
      FILE *outfile) 
 
1270
{
 
1271
   double *twoel_ints;
 
1272
   int i, max_pq;
 
1273
   struct iwlbuf inbuf, outbuf;
 
1274
   
 
1275
   /* may be slightly more than pq_per_bucket pq's in each bucket
 
1276
    * if the pq's didn't divide evenly among the buckets.  The remainder
 
1277
    * will go to the last bucket.
 
1278
    */
 
1279
   max_pq = YBuff->buckets[YBuff->core_loads-1].hi - 
 
1280
            YBuff->buckets[YBuff->core_loads-1].lo
 
1281
            + 1;
 
1282
 
 
1283
   twoel_ints = init_array(max_pq * ket_indices) ;
 
1284
   iwl_buf_init(&outbuf, out_tape, YBuff->cutoff, 0, 0);
 
1285
 
 
1286
   for (i=0; i<YBuff->core_loads-1; i++) {
 
1287
      if (print_lvl > 1) fprintf(outfile, "Sorting bin %d\n", i+1);
 
1288
      iwl_buf_init(&inbuf, YBuff->first_tmp_file+i, YBuff->cutoff, 1, 0);
 
1289
      sortbuf(&inbuf, &outbuf, twoel_ints, (YBuff->buckets)[i].lo, 
 
1290
              (YBuff->buckets)[i].hi, ioff, ioff2, nbfso, elbert,
 
1291
               intermediate, no_pq_perm, qdim, add, (print_lvl > 4), outfile);
 
1292
      zero_arr(twoel_ints, max_pq * ket_indices);
 
1293
      /* zero_arr(twoel_ints, YBuff->pq_per_bucket * YBuff->bra_indices); */
 
1294
      iwl_buf_close(&inbuf, keep_bins);
 
1295
      }
 
1296
 
 
1297
 
 
1298
   if (print_lvl > 1) fprintf(outfile, "Sorting bin %d\n", i+1) ;
 
1299
   iwl_buf_init(&inbuf, YBuff->first_tmp_file+i, YBuff->cutoff, 1, 0);
 
1300
   sortbuf(&inbuf, &outbuf, twoel_ints, (YBuff->buckets)[i].lo, 
 
1301
           (YBuff->buckets)[i].hi, ioff, ioff2, nbfso, elbert, 
 
1302
           intermediate, no_pq_perm, qdim, add, (print_lvl > 4), outfile);
 
1303
   iwl_buf_close(&inbuf, keep_bins);
 
1304
   
 
1305
   if (print_lvl > 1) fprintf(outfile, "Done sorting.\n");
 
1306
   
 
1307
   iwl_buf_flush(&outbuf, 1);
 
1308
   iwl_buf_close(&outbuf, 1);
 
1309
   free(twoel_ints);
 
1310
}
 
1311
 
 
1312
 
 
1313
/*
 
1314
** YOSH_FREE(): Free up a Yoshimine object.  Free any dynamically-allocated
 
1315
**    memory.
 
1316
*/
 
1317
void yosh_free(struct yoshimine *YBuff)
 
1318
{
 
1319
   free(YBuff->buckets);
 
1320
}
 
1321
 
 
1322
 
 
1323
/*
 
1324
** YOSH_FLUSH(): Flush any of the buckets and tag them as 'last buffer'
 
1325
**    for each bucket tmp file.
 
1326
**
 
1327
*/
 
1328
void yosh_flush(struct yoshimine *YBuff)
 
1329
{
 
1330
   int i;
 
1331
 
 
1332
   for (i=0; i<YBuff->nbuckets; i++) {
 
1333
         flush_bucket((YBuff->buckets)+i, 1);
 
1334
      }
 
1335
}
 
1336
 
 
1337
 
 
1338
 
 
1339
/*
 
1340
** FLUSH_BUCKET():  This function flushes a Yoshimine bucket to a temporary
 
1341
**    binary file.  Must be careful to call with lastbuf==1 when the
 
1342
**    last buffer has been reached, so that the iwl buffer can set the
 
1343
**    `last buffer' flag on output.
 
1344
*/
 
1345
void flush_bucket(struct bucket *bptr, int lastbuf)
 
1346
{
 
1347
 
 
1348
   iwl_buf_wrt_arr(&(bptr->IWLBuf), bptr->val, bptr->p, bptr->q, 
 
1349
     bptr->r, bptr->s, bptr->in_bucket);
 
1350
   iwl_buf_flush(&(bptr->IWLBuf), lastbuf);
 
1351
}
 
1352
 
 
1353
 
 
1354
/*
 
1355
** YOSH_WRT_ARR(): Write an array to a Yoshimine object...useful for writing
 
1356
**    intermediates to disk from a transformation program.  Write only 
 
1357
**    nonzero elements so that less disk space is required, and so that
 
1358
**    zeroes for i,j,k,l and value for the first element in a buffer can
 
1359
**    indicate an empty buffer.  (Eventually I should probably use
 
1360
**    the second byte of the flags field in each buffer to indicate a
 
1361
**    zero buffer, else use the second and third bytes to denote the
 
1362
**    number of integrals in each buffer.  File34 had a field like
 
1363
**    this, but it assumes an integral number of integer words per
 
1364
**    double, which might not be true in the long run.  IWL is currently
 
1365
**    free of this assumption).
 
1366
**
 
1367
**    The sortbuf() routine wants to have blocks containing all rs for
 
1368
**    a given pq.  If instead, we want all pq for a given rs, we
 
1369
**    need to reverse the order of pq and rs in the tmp files.  Set
 
1370
**    sortby_rs=1.
 
1371
**
 
1372
** Arguments:
 
1373
**    YBuff     =  pointer to Yoshimine object
 
1374
**    p         =  common p value for array
 
1375
**    q         =  common q value for array
 
1376
**    pq        =  compound index determined from p and q
 
1377
**    pqsym     =  the direct product of the symmetries of p and q
 
1378
**    arr       =  the array containing the data for a given pq
 
1379
**    rmax      =  the maximum value of the third index 
 
1380
**    ioff      =  the standard offset array
 
1381
**    orbsym    =  the irrep for each orbital
 
1382
**    firsti    =  the first orbital for each irrep
 
1383
**    lasti     =  last orbital for each irrep
 
1384
**    sortby_rs =  described above
 
1385
**    printflag =  verbosity level for printing
 
1386
**    outfile   =  text output file
 
1387
**    
 
1388
*/
 
1389
void yosh_wrt_arr(struct yoshimine *YBuff, int p, int q, int pq, int pqsym,
 
1390
   double *arr, int rmax, int *ioff, int *orbsym, int *firsti, 
 
1391
   int *lasti, int sortby_rs, int printflag, FILE *outfile)
 
1392
{
 
1393
   int r, s, rs, rsym, ssym, smax;
 
1394
   long int tmpi;
 
1395
   int whichbucket;
 
1396
   int lastflag = 0, firstfile;
 
1397
   struct bucket *bptr;
 
1398
   double value;
 
1399
 
 
1400
   if (printflag) {
 
1401
     fprintf(outfile, "\nyosh_wrt_arr called for p=%d,q=%d\n", p, q);
 
1402
   }
 
1403
 
 
1404
   firstfile = YBuff->first_tmp_file;
 
1405
 
 
1406
   for (r=0; r<rmax; r++) {
 
1407
      rsym = orbsym[r];
 
1408
      ssym = pqsym ^ rsym;
 
1409
      if (ssym > rsym) continue;
 
1410
 
 
1411
      smax = (rsym == ssym) ? r : lasti[ssym];
 
1412
 
 
1413
      for (s=firsti[ssym]; s<=smax; s++) {
 
1414
         rs = ioff[r] + s;
 
1415
         value = arr[rs];
 
1416
 
 
1417
         if (fabs(value) > YBuff->cutoff) {
 
1418
            /* figure out which bucket the integral should go in */
 
1419
            if (sortby_rs) whichbucket = YBuff->bucket_for_pq[rs];
 
1420
            else whichbucket = YBuff->bucket_for_pq[pq];
 
1421
 
 
1422
            bptr = YBuff->buckets+whichbucket ;
 
1423
            tmpi = (bptr->in_bucket)++ ;
 
1424
 
 
1425
            /* sortbuf wants to sort by the first index.  If we want to
 
1426
             * sort by rs, we need to map r->p, s->q, p->r, q->s 
 
1427
             */
 
1428
            if (sortby_rs) {
 
1429
               bptr->p[tmpi] = r;
 
1430
               bptr->q[tmpi] = s;
 
1431
               bptr->r[tmpi] = p;
 
1432
               bptr->s[tmpi] = q;
 
1433
               } 
 
1434
            else {
 
1435
               bptr->p[tmpi] = p;
 
1436
               bptr->q[tmpi] = q;
 
1437
               bptr->r[tmpi] = r;
 
1438
               bptr->s[tmpi] = s;
 
1439
               }
 
1440
 
 
1441
            bptr->val[tmpi] = value;
 
1442
 
 
1443
            if (printflag)
 
1444
               fprintf(outfile, "%4d %4d %4d %4d  %10.6lf\n", 
 
1445
                  p, q, r, s, arr[rs]);
 
1446
 
 
1447
            /* if we need to flush bucket to disk */
 
1448
            if ((tmpi+1) == YBuff->bucketsize) { 
 
1449
               flush_bucket(bptr, lastflag);
 
1450
               bptr->in_bucket = 0 ;
 
1451
               }
 
1452
 
 
1453
            /* 
 
1454
             * What if this was the last buffer, and we didn't set the lastbuf
 
1455
             * flag?  Must write a buffer of zeroes using the yosh_flush() 
 
1456
             * routine.  Must be careful to always have the last buffer
 
1457
             * set the lastbuf flag (to avoid read error) and must also be
 
1458
             * sure that an exactly-filled buffer is written out.  Carelessness
 
1459
             * might cause a failure to write the last buffer if it has
 
1460
             * exactly 'bucketsize' elements. ---CDS
 
1461
             */ 
 
1462
 
 
1463
            } /* end if (fabs(arr[rs])) ... */
 
1464
 
 
1465
         } /* end loop over s */
 
1466
 
 
1467
      }  /* end loop over r */
 
1468
 
 
1469
   if (printflag) fflush(outfile);
 
1470
  
 
1471
}
 
1472
 
 
1473
 
 
1474
/*
 
1475
** YOSH_WRT_ARR2(): Write an array to a Yoshimine object (nonzero
 
1476
**    elements only).  The values of the integrals are in array 'arr',
 
1477
**    and the indices are input as follows:  all integrals have the 
 
1478
**    common indices 'p' and 'q'.  The remaining indices are input
 
1479
**    in arrays 'rlist' and 'slist'.  The number of integrals in the
 
1480
**    current block is given by the parameter 'size'.  As currently
 
1481
**    written, the routine will write out the integrals in canonical
 
1482
**    ordering p>=q, r>=s, pq>=rs.  It might conceivably be useful
 
1483
**    in the future to use a 'sortby_rs' flag as in yosh_wrt_arr().
 
1484
**
 
1485
** Arguments:
 
1486
**    YBuff     =  pointer to Yoshimine object
 
1487
**    size      =  number of integrals to process in the array
 
1488
**    arr       =  the array containing the data for a given pq
 
1489
**    p         =  common p value for array
 
1490
**    q         =  common q value for array
 
1491
**    rlist     =  list of indices r
 
1492
**    slist     =  list of indices s (no guarantee rlist[i] >= slist[i])
 
1493
**    ioff      =  the standard offset array
 
1494
**    printflag =  verbosity level for printing
 
1495
**    outfile   =  text output file
 
1496
**    
 
1497
*/
 
1498
void yosh_wrt_arr2(struct yoshimine *YBuff, int size, double *arr, 
 
1499
   int p, int q, int *rlist, int *slist, int *ioff, int printflag,
 
1500
   FILE *outfile)
 
1501
{
 
1502
   int x;
 
1503
   int i1, j1, k1, l1, ij1, kl1;
 
1504
   int ktmp, ltmp;
 
1505
   int i2, j2, k2, l2, ij2, kl2;
 
1506
   long int tmpi;
 
1507
   int whichbucket;
 
1508
   int lastflag = 0, firstfile;
 
1509
   struct bucket *bptr;
 
1510
   double value;
 
1511
 
 
1512
   firstfile = YBuff->first_tmp_file;
 
1513
 
 
1514
   i1 = MAX0(p,q);
 
1515
   j1 = MIN0(p,q);
 
1516
   ij1 = ioff[i1] + j1;
 
1517
 
 
1518
   for (x=0; x<size; x++) {
 
1519
      
 
1520
      value = *arr++;
 
1521
      ktmp = *rlist++;
 
1522
      ltmp = *slist++;
 
1523
      
 
1524
      if (fabs(value) < YBuff->cutoff) continue;
 
1525
 
 
1526
      k1 = MAX0(ktmp,ltmp);
 
1527
      l1 = MIN0(ktmp,ltmp);
 
1528
      kl1 = ioff[k1] + l1;
 
1529
 
 
1530
      if (ij1 < kl1) {
 
1531
         i2 = k1;
 
1532
         j2 = l1;
 
1533
         k2 = i1;
 
1534
         l2 = j1;
 
1535
         ij2 = kl1;
 
1536
         kl2 = ij1;
 
1537
         }
 
1538
      else {
 
1539
         i2 = i1;
 
1540
         j2 = j1;
 
1541
         k2 = k1;
 
1542
         l2 = l1;
 
1543
         ij2 = ij1;
 
1544
         kl2 = kl1;
 
1545
         }
 
1546
 
 
1547
   whichbucket = YBuff->bucket_for_pq[ij2];
 
1548
   bptr = YBuff->buckets+whichbucket ;
 
1549
   tmpi = (bptr->in_bucket)++ ;
 
1550
 
 
1551
   bptr->p[tmpi] = i2;
 
1552
   bptr->q[tmpi] = j2;
 
1553
   bptr->r[tmpi] = k2;
 
1554
   bptr->s[tmpi] = l2;
 
1555
 
 
1556
   bptr->val[tmpi] = value;
 
1557
 
 
1558
   if (printflag) fprintf(outfile, "%4d %4d %4d %4d  %10.6lf\n", 
 
1559
         i2, j2, k2, l2, value);
 
1560
 
 
1561
   /* if we need to flush bucket to disk */
 
1562
      if ((tmpi+1) == YBuff->bucketsize) { 
 
1563
         flush_bucket(bptr, lastflag);
 
1564
         bptr->in_bucket = 0;
 
1565
         }
 
1566
 
 
1567
   } /* end loop over x */
 
1568
 
 
1569
}
 
1570
 
 
1571
/*
 
1572
** YOSH_WRT_ARR_MP2(): Write an array to a Yoshimine object...useful for
 
1573
**    writing intermediates to disk from a transformation program.  Write
 
1574
**    only nonzero elements so that less disk space is required, and so that
 
1575
**    zeroes for i,j,k,l and value for the first element in a buffer can
 
1576
**    indicate an empty buffer.
 
1577
**
 
1578
**    The sortbuf() routine wants to have blocks containing all rs for
 
1579
**    a given pq.  If instead, we want all pq for a given rs, we
 
1580
**    need to reverse the order of pq and rs in the tmp files.  Set
 
1581
**    sortby_rs=1.
 
1582
**
 
1583
**    This routine has been altered to work _only_ for MP2 restricted
 
1584
**    sorts.  It expects the r-index to correlate to occupied orbitals and
 
1585
**    the s-index to virtual orbitals.  This routine may not, in general
 
1586
**    be used with other orbital distributions.
 
1587
**    -Daniel 9/20/95
 
1588
**
 
1589
** Arguments:
 
1590
**    YBuff     =  pointer to Yoshimine object
 
1591
**    p         =  common p value for array
 
1592
**    q         =  common q value for array
 
1593
**    pq        =  compound index determined from p and q
 
1594
**    pqsym     =  the direct product of the symmetries of p and q
 
1595
**    arr       =  the array containing the data for a given pq
 
1596
**    rsym      =  the irrep of the r-indices
 
1597
**    firstr    =  the first r-index for each irrep
 
1598
**    lastr     =  the last r-index for each irrep
 
1599
**    firsts    =  the first s-index for each irrep
 
1600
**    lasts     =  the last s-index for each irrep
 
1601
**    sortby_rs =  described above
 
1602
**    ndocc     =  the number of doubly-occupied orbitals
 
1603
**    nvirt     =  the number of virtual orbitals
 
1604
**    occ       =  the Pitzer -> QTS ordering array for the occupied orbitals
 
1605
**    vir       =  the Pitzer -> QTS ordering array for the virtual orbitals
 
1606
**    ioff3     =  offset array for ndocc*nvirt arrays
 
1607
**    printflag =  verbosity level for printing
 
1608
**    outfile   =  text output file
 
1609
**    
 
1610
*/
 
1611
void yosh_wrt_arr_mp2(struct yoshimine *YBuff, int p, int q, int pq,
 
1612
                      int pqsym, double **arr, int rsym, int *firstr,
 
1613
                      int *lastr, int *firsts, int *lasts, int sortby_rs,
 
1614
                      int ndocc, int nvirt, int *occ, int *vir, int *ioff3,
 
1615
                      int printflag, FILE *outfile)
 
1616
{
 
1617
   int r, s, rs, ssym;
 
1618
   int rnew,snew;
 
1619
   int R,S;
 
1620
   long int tmpi;
 
1621
   int whichbucket;
 
1622
   int lastflag = 0, firstfile;
 
1623
   struct bucket *bptr;
 
1624
   double value;
 
1625
 
 
1626
   firstfile = YBuff->first_tmp_file;
 
1627
   ssym = pqsym ^ rsym;
 
1628
   for (r=firstr[rsym], R=0; r <= lastr[rsym]; r++, R++) {
 
1629
       rnew = occ[r];
 
1630
      for (s=firsts[ssym], S=0; s <=lasts[ssym]; s++, S++) {
 
1631
          snew = vir[s];
 
1632
          rs = ioff3[rnew] + snew;
 
1633
          value = arr[R][S];
 
1634
 
 
1635
         if (fabs(value) > YBuff->cutoff) {
 
1636
            /* figure out which bucket the integral should go in */
 
1637
            if (sortby_rs) whichbucket = YBuff->bucket_for_pq[rs];
 
1638
            else whichbucket = YBuff->bucket_for_pq[pq];
 
1639
 
 
1640
            bptr = YBuff->buckets+whichbucket ;
 
1641
            tmpi = (bptr->in_bucket)++ ;
 
1642
 
 
1643
            /* sortbuf wants to sort by the first index.  If we want to
 
1644
             * sort by rs, we need to map r->p, s->q, p->r, q->s
 
1645
             * We also write out the QTS ordered indices for r and s, and
 
1646
             * not the Pitzer indices.
 
1647
             */
 
1648
            if (sortby_rs) {
 
1649
               bptr->p[tmpi] = rnew;
 
1650
               bptr->q[tmpi] = snew;
 
1651
               bptr->r[tmpi] = p;
 
1652
               bptr->s[tmpi] = q;
 
1653
               } 
 
1654
            else {
 
1655
               bptr->p[tmpi] = p;
 
1656
               bptr->q[tmpi] = q;
 
1657
               bptr->r[tmpi] = rnew;
 
1658
               bptr->s[tmpi] = snew;
 
1659
               }
 
1660
 
 
1661
            bptr->val[tmpi] = value;
 
1662
 
 
1663
            if (printflag)
 
1664
               fprintf(outfile, "%4d %4d %4d %4d  %10.6lf\n", 
 
1665
                  p, q, r, s, value);
 
1666
 
 
1667
            /* if we need to flush bucket to disk */
 
1668
            if ((tmpi+1) == YBuff->bucketsize) { 
 
1669
               flush_bucket(bptr, lastflag);
 
1670
               bptr->in_bucket = 0;
 
1671
               }
 
1672
 
 
1673
            } /* end if (fabs(arr[rs])) ... */
 
1674
 
 
1675
         } /* end loop over s */
 
1676
 
 
1677
      }  /* end loop over r */
 
1678
 
 
1679
}
 
1680
 
 
1681
 
 
1682
 
 
1683
/*
 
1684
** YOSH_WRT_ARR_MP2R12A(): Write an array to a Yoshimine object...useful for
 
1685
**    writing intermediates to disk from a transformation program.  Write
 
1686
**    only nonzero elements so that less disk space is required, and so that
 
1687
**    zeroes for i,j,k,l and value for the first element in a buffer can
 
1688
**    indicate an empty buffer.
 
1689
**
 
1690
**    The sortbuf() routine wants to have blocks containing all rs for
 
1691
**    a given pq.  If instead, we want all pq for a given rs, we
 
1692
**    need to reverse the order of pq and rs in the tmp files.  Set
 
1693
**    sortby_rs=1.
 
1694
**
 
1695
**    This routine has been altered to work _only_ for MP2R12A restricted
 
1696
**    sorts.  It expects the r-index to correlate to occupied orbitals.
 
1697
**    This routine may not, in general
 
1698
**    be used with other orbital distributions.
 
1699
**    -Edward
 
1700
**
 
1701
** Arguments:
 
1702
**    YBuff     =  pointer to Yoshimine object
 
1703
**    p         =  common p value for array
 
1704
**    q         =  common q value for array
 
1705
**    pq        =  compound index determined from p and q
 
1706
**    pqsym     =  the direct product of the symmetries of p and q
 
1707
**    arr       =  the array containing the data for a given pq
 
1708
**    rsym      =  the irrep of the r-indices
 
1709
**    firstr    =  the first r-index for each irrep
 
1710
**    lastr     =  the last r-index for each irrep
 
1711
**    firsts    =  the first s-index for each irrep
 
1712
**    lasts     =  the last s-index for each irrep
 
1713
**    sortby_rs =  described above
 
1714
**    occ       =  the Pitzer -> QTS ordering array for the occupied orbitals
 
1715
**    ioff3     =  offset array for ndocc*nmo arrays
 
1716
**    printflag =  verbosity level for printing
 
1717
**    outfile   =  text output file
 
1718
**    
 
1719
*/
 
1720
void yosh_wrt_arr_mp2r12a(struct yoshimine *YBuff, int p, int q, int pq,
 
1721
                          int pqsym, double **arr, int rsym, int *firstr,
 
1722
                          int *lastr, int *firsts, int *lasts, int sortby_rs,
 
1723
                          int *occ, int *ioff3,
 
1724
                          int printflag, FILE *outfile)
 
1725
{
 
1726
   int r, s, rs, ssym;
 
1727
   int rnew,snew;
 
1728
   int R,S;
 
1729
   long int tmpi;
 
1730
   int whichbucket;
 
1731
   int lastflag = 0, firstfile;
 
1732
   struct bucket *bptr;
 
1733
   double value;
 
1734
 
 
1735
   firstfile = YBuff->first_tmp_file;
 
1736
   ssym = pqsym ^ rsym;
 
1737
   for (r=firstr[rsym], R=0; r <= lastr[rsym]; r++, R++) {
 
1738
       rnew = occ[r];
 
1739
      for (s=firsts[ssym], S=0; s <=lasts[ssym]; s++, S++) {
 
1740
          snew = s;
 
1741
          rs = ioff3[rnew] + snew;
 
1742
          value = arr[R][S];
 
1743
 
 
1744
         if (fabs(value) > YBuff->cutoff) {
 
1745
            /* figure out which bucket the integral should go in */
 
1746
            if (sortby_rs) whichbucket = YBuff->bucket_for_pq[rs];
 
1747
            else whichbucket = YBuff->bucket_for_pq[pq];
 
1748
 
 
1749
            bptr = YBuff->buckets+whichbucket ;
 
1750
            tmpi = (bptr->in_bucket)++ ;
 
1751
 
 
1752
            /* sortbuf wants to sort by the first index.  If we want to
 
1753
             * sort by rs, we need to map r->p, s->q, p->r, q->s
 
1754
             * We also write out the QTS ordered index for r, and
 
1755
             * not the Pitzer index.
 
1756
             */
 
1757
            if (sortby_rs) {
 
1758
               bptr->p[tmpi] = rnew;
 
1759
               bptr->q[tmpi] = snew;
 
1760
               bptr->r[tmpi] = p;
 
1761
               bptr->s[tmpi] = q;
 
1762
               } 
 
1763
            else {
 
1764
               bptr->p[tmpi] = p;
 
1765
               bptr->q[tmpi] = q;
 
1766
               bptr->r[tmpi] = rnew;
 
1767
               bptr->s[tmpi] = snew;
 
1768
               }
 
1769
 
 
1770
            bptr->val[tmpi] = value;
 
1771
 
 
1772
            if (printflag)
 
1773
               fprintf(outfile, "%4d %4d %4d %4d  %10.6lf\n", 
 
1774
                  p, q, r, s, value);
 
1775
 
 
1776
            /* if we need to flush bucket to disk */
 
1777
            if ((tmpi+1) == YBuff->bucketsize) { 
 
1778
               flush_bucket(bptr, lastflag);
 
1779
               bptr->in_bucket = 0;
 
1780
               }
 
1781
 
 
1782
            } /* end if (fabs(arr[rs])) ... */
 
1783
 
 
1784
         } /* end loop over s */
 
1785
 
 
1786
      }  /* end loop over r */
 
1787
}
 
1788
 
 
1789
}} // end namespace psi::transqt
 
1790