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

« back to all changes in this revision

Viewing changes to src/lib/libiwl/sortbuf.c

  • 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
 
/*!
2
 
  \file sortbuf.c
3
 
  \ingroup (IWL)
4
 
*/
5
 
#include <stdio.h>
6
 
#include <math.h>
7
 
#include <libciomr/libciomr.h>
8
 
#include "iwl.h"
9
 
 
10
 
#define MIN0(a,b) (((a)<(b)) ? (a) : (b))
11
 
#define MAX0(a,b) (((a)>(b)) ? (a) : (b))
12
 
 
13
 
#define BIGNUM 40000
14
 
 
15
 
/*!
16
 
** sortbuf()
17
 
**
18
 
** Function reads a file of two-electron integrals into
19
 
** core and writes them back out again in canonical order.  Used in
20
 
** Yoshimine sorts where we have a file containing all rs for a few
21
 
** values of pq, but the ints are not in canonical order.  At the 
22
 
** very least, we need to sort to make sure that all (pq|rs) for a
23
 
** given pq are grouped together, since the transformation program
24
 
** wants to work with all rs for a single pq value at one time.
25
 
** We may or may not use the restriction pq >= rs (not used if 
26
 
** intermediate = 1, which is how this routine is always called
27
 
** right now).
28
 
**
29
 
** One interesting issue here is that the intermediate array ('ints')
30
 
** must be big enough to hold the integrals in the current buffer, but
31
 
** we don't generally want it to be much larger than necessary!  Thus
32
 
** we calculate an 'offset' which is the canonical index of the first
33
 
** integral in the buffer, and we use this so that the first integral
34
 
** in the buffer is stored in ints[0].  What's different for the
35
 
** Elbert ordering is that we have all rs for a given pq but rs >= pq!
36
 
** If we want our canonical indices to be consecutive WITHIN THE
37
 
** CURRENT BUFFER, we MUST use upper triangle ordering rather than 
38
 
** lower triangle!  That's what ioff2 is used for.  Obviously the
39
 
** offset must also be calculated with ioff2 for the Elbert order.
40
 
** Formula for ioff2: ioff2[0] = 0; ioff2[i] = ioff2[i-1] + n - i;
41
 
** Note that this is not the case when this routine is used for MP2
42
 
** sorts.  The definitions of the ioff arrays can be confusing, so
43
 
** care should be taken when using this routine.
44
 
**
45
 
**    \param Inbuf       = IWL buffer for input
46
 
**    \param Outbuf      = IWL buffer for output
47
 
**    \param ints        = array to hold integrals in
48
 
**    \param fpq         = first pq for this tape
49
 
**    \param lpq         = last pq for this tape 
50
 
**    \param ioff        = offset array for the left indices
51
 
**    \param ioff2       = offset array for Elbert sorts or for the right 
52
 
**                  indices when no_pq_perm=1 
53
 
**    \param nbfso       = number of basis functions in SO's
54
 
**    \param lastsort    = 1 if this is the last intape, 0 otherwise
55
 
**    \param elbert      = integrals obey rs >= pq.  Use ioff2 to get offset.
56
 
**    \param intermediate= 1 if sorting a intermediate in the transformation
57
 
**                  which is indexed as X[ij][kl] where ij runs from
58
 
**                  fpq to lpq and kl runs from 0 to nbstri
59
 
**    \param no_pq_perm  = don't use permutational symmetry to swap p and q
60
 
**                  (appropriate for MP2 where one is occ and one is virt)
61
 
**    \param qdim        = dimensions for the q index...nvirt for MP2
62
 
**    \param add         = add contributions to the same integral during sort
63
 
**    \param printflg    = 1 for printing, 0 otherwise
64
 
**    \param outfile     = output file pointer
65
 
**
66
 
** Returns: none
67
 
**
68
 
** Revised 6/27/96 by CDS for new IWL format
69
 
** N.B. Now need to iwl_flush the output buffer...not done in here!!
70
 
** \ingroup (IWL)
71
 
*/
72
 
void sortbuf(struct iwlbuf *Inbuf, struct iwlbuf *Outbuf,
73
 
      double *ints, int fpq, int lpq, int *ioff, int *ioff2, 
74
 
      int nbfso, int elbert, int intermediate, int no_pq_perm, 
75
 
      int qdim, int add, int printflg, FILE *outfile) 
76
 
{
77
 
   int i;
78
 
   Value *valptr;              /* array of integral values */
79
 
   Label *lblptr;              /* array of integral labels */
80
 
   int idx;                    /* index for curr integral (0..ints_per_buf) */
81
 
   int lastbuf;                /* last buffer flag */
82
 
   int p, q, qmax, qmin, r, rmin, rmax, s, smin, smax, pq, rs;
83
 
   long int pqrs, offset;
84
 
   int first_p, first_q, first_pq, last_p, last_q;
85
 
   int nbstri;
86
 
 
87
 
   if (printflg) {
88
 
     fprintf(outfile, "\nsortbuf for pq=%d to %d\n", fpq, lpq);
89
 
   }
90
 
 
91
 
   if (no_pq_perm && !intermediate) {
92
 
     fprintf(outfile,"(sortbuf): illegal parameter combination.\n");
93
 
     fprintf(stderr, "(sortbuf): illegal parameter combination.\n");
94
 
   }
95
 
   
96
 
   nbstri = nbfso * (nbfso + 1) / 2;
97
 
   
98
 
   /* figure out ranges on things */
99
 
   /* I believe this section works fine, even with different ioff arrays */
100
 
   i = 0;
101
 
   while (fpq >= ioff[i] && i < BIGNUM) i++;
102
 
   if (i == BIGNUM) {
103
 
     fprintf(outfile, "(sortbuf): parameter error\n") ;
104
 
     return;
105
 
   }
106
 
   first_p = i-1 ; first_q = fpq - ioff[i-1];
107
 
   first_pq = ioff[first_p] + first_q;
108
 
   if (first_pq != fpq) {
109
 
     fprintf(outfile, "(sortbuf): fpq != first_pq.\n");
110
 
     fprintf(stderr,  "(sortbuf): fpq != first_pq.\n");
111
 
   }
112
 
   
113
 
   if (!intermediate) {
114
 
     if (elbert) offset = ioff2[first_pq] + first_pq ;
115
 
     else offset = ioff[first_pq] ;
116
 
   }
117
 
   else offset = 0;
118
 
 
119
 
   i=0; 
120
 
   while (lpq >= ioff[i] && i < BIGNUM) i++ ;
121
 
   if (i == BIGNUM) {
122
 
     fprintf(outfile, "(sortbuf): parameter error\n") ;
123
 
     return ;
124
 
   }
125
 
   last_p = i-1 ; last_q = lpq - ioff[i-1] ;
126
 
   
127
 
   
128
 
   lblptr = Inbuf->labels;
129
 
   valptr = Inbuf->values;
130
 
 
131
 
   /* read a buffer at a time until we're done */
132
 
 
133
 
   do {
134
 
      iwl_buf_fetch(Inbuf);
135
 
      lastbuf = Inbuf->lastbuf;
136
 
      for (idx=4*Inbuf->idx; Inbuf->idx<Inbuf->inbuf; Inbuf->idx++) {
137
 
        p = (int) lblptr[idx++];
138
 
        q = (int) lblptr[idx++];
139
 
        r = (int) lblptr[idx++];
140
 
        s = (int) lblptr[idx++];
141
 
 
142
 
        /* if (no_pq_perm) ioff is the appropriate offset array for the left
143
 
           indices (ioff[p] = nvirt * p for MP2); ioff2 is then the usual
144
 
           ioff offset array, used for the right indices */
145
 
        if (no_pq_perm) {
146
 
          pq = ioff[p] + q;
147
 
          rs = ioff2[MAX0(r,s)] + MIN0(r,s);
148
 
        }
149
 
        else {
150
 
          pq = ioff[MAX0(p,q)] + MIN0(p,q);
151
 
          rs = ioff[MAX0(r,s)] + MIN0(r,s);
152
 
        }
153
 
        
154
 
        if (!intermediate) {
155
 
          if (elbert)
156
 
            pqrs = ioff2[pq] + rs;
157
 
          else {
158
 
            pqrs = ioff[MAX0(pq,rs)];
159
 
            pqrs += MIN0(pq,rs);
160
 
          }
161
 
        }
162
 
        else {
163
 
          pqrs = (pq - first_pq);
164
 
          pqrs *= nbstri;
165
 
          pqrs += rs;
166
 
        }
167
 
        
168
 
        if (printflg && ints[pqrs-offset] != 0.0) 
169
 
           fprintf(outfile, "Adding %10.6lf to el %d %d %d %d = %10.6lf\n", 
170
 
                   valptr[Inbuf->idx], p, q, r, s, ints[pqrs-offset]);
171
 
 
172
 
        if (add) ints[pqrs-offset] += valptr[Inbuf->idx];
173
 
        else ints[pqrs-offset] += valptr[Inbuf->idx];
174
 
 
175
 
        if (printflg) 
176
 
          fprintf(outfile, "<%d %d %d %d | %d %d [%ld] = %10.6lf\n",
177
 
                  p, q, r, s, pq, rs, pqrs, ints[pqrs-offset]) ;
178
 
      }
179
 
   } while (!lastbuf);
180
 
   
181
 
   /* now write them out again, in order */
182
 
   lblptr = Outbuf->labels;
183
 
   valptr = Outbuf->values;
184
 
 
185
 
   idx = 0;
186
 
 
187
 
   for (p=first_p; p<=last_p; p++) {
188
 
     qmax = (p==last_p) ? last_q : p ;
189
 
     qmin = (p==first_p) ? first_q : 0 ;
190
 
     if(no_pq_perm) {
191
 
       qmax = (p==last_p) ? last_q : (qdim-1);
192
 
       qmin = (p==first_p) ? first_q: 0;
193
 
     }
194
 
     for (q=qmin; q<=qmax; q++) {
195
 
       pq = ioff[p] + q ; /* This should be fine even with MP2 */
196
 
       
197
 
       if (!intermediate) {
198
 
         rmin = (elbert) ? p : 0 ; 
199
 
         rmax = (elbert) ? nbfso : p+1 ;
200
 
       }
201
 
       else {  /* This should be fine with MP2, also */
202
 
         rmin = 0;
203
 
         rmax = nbfso;
204
 
       }
205
 
       
206
 
       for (r=rmin; r<rmax; r++) {
207
 
         
208
 
         if (!intermediate) {
209
 
           if (elbert) {
210
 
             smax = r+1 ;
211
 
             smin = (p==r) ? q : 0 ;
212
 
           }
213
 
           else {
214
 
             smax = (p==r) ? (q+1) : (r+1) ;
215
 
             smin = 0 ;
216
 
           }
217
 
         }
218
 
         else { /* This should be fine with MP2, also */
219
 
           smax = r + 1;
220
 
           smin = 0;
221
 
         }
222
 
         
223
 
         for (s=smin; s < smax; s++) {
224
 
           if(no_pq_perm) rs = ioff2[r] + s;
225
 
           else rs = ioff[r] + s;
226
 
           
227
 
           /* Again, this should be fine with MP2 */
228
 
           if (elbert) pqrs = ioff2[pq] + rs ;
229
 
           else if (intermediate) {
230
 
             pqrs = (pq - first_pq);
231
 
             pqrs *= nbstri;
232
 
             pqrs += rs;
233
 
           }
234
 
           else pqrs = ioff[pq] + rs ;
235
 
           
236
 
           if (fabs(ints[pqrs-offset]) > Outbuf->cutoff) {
237
 
             idx = 4*Outbuf->idx;
238
 
             lblptr[idx++] = p;
239
 
             lblptr[idx++] = q;
240
 
             lblptr[idx++] = r;
241
 
             lblptr[idx++] = s;
242
 
             valptr[Outbuf->idx] = ints[pqrs-offset];
243
 
             if (printflg) 
244
 
               fprintf(outfile, ">%d %d %d %d | %d %d [%ld] = %10.6lf\n",
245
 
                       p, q, r, s, pq, rs, pqrs, ints[pqrs-offset]) ;
246
 
             
247
 
             Outbuf->idx++;
248
 
             if (Outbuf->idx == Outbuf->ints_per_buf) {
249
 
               Outbuf->lastbuf = 0;
250
 
               Outbuf->inbuf = Outbuf->idx;
251
 
               iwl_buf_put(Outbuf);
252
 
               Outbuf->idx = 0;
253
 
             } 
254
 
           }
255
 
         }
256
 
       }
257
 
     }
258
 
   }
259
 
   
260
 
}
261
 
 
262