~ubuntu-branches/ubuntu/precise/psicode/precise

« back to all changes in this revision

Viewing changes to src/bin/localize/local.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
 
#include <stdio.h>
2
 
#include <stdlib.h>
3
 
#include <math.h>
4
 
#include <libciomr/libciomr.h>
5
 
#include <libint/libint.h>
6
 
#include <libchkpt/chkpt.h>
7
 
#include <libiwl/iwl.h>
8
 
#include <psifiles.h>
9
 
#include <libqt/qt.h>
10
 
 
11
 
FILE *infile, *outfile;
12
 
char *psi_file_prefix;
13
 
 
14
 
void init_io(int argc, char *argv[]);
15
 
void exit_io(void);
16
 
void title(void);
17
 
 
18
 
int main(int argc, char *argv[])
19
 
{
20
 
  int iter, s, t, A, k, l, m, p, q, inew, iold, max, max_col, phase_ok, phase_chk;
21
 
  int i, j, ij, am, atom, shell_length, offset, stat;
22
 
  int nirreps, nao, nmo, nso, natom, nshell, noei, nocc, errcod, nfzc;
23
 
  int *stype, *snuc, *aostart, *aostop, *ao2atom, *l_length;
24
 
  int *clsdpi, *openpi, *orbspi, *dummy, *order, *frdocc;
25
 
  double *ss, **S, **scf, **u, **Ctmp, **C, *evals, **MO_S, **scf_old, **X;
26
 
 
27
 
  int *orb_order, *orb_boolean, puream;
28
 
  double P, PiiA, Pst, Pss, Ptt, Ast, Bst, AB;
29
 
  double Uss, Utt, Ust, Uts, Cks, Ckt, **U, **V, **VV, **F;
30
 
  double cos4a, alpha, alphamax, alphalast, conv, norm;
31
 
  int print;
32
 
 
33
 
  alphalast = 1.0;
34
 
 
35
 
  init_io(argc, argv);
36
 
  title();
37
 
 
38
 
  chkpt_init(PSIO_OPEN_OLD);
39
 
  nao = chkpt_rd_nao();
40
 
  nmo = chkpt_rd_nmo();
41
 
  nso = chkpt_rd_nso();
42
 
  natom = chkpt_rd_natom();
43
 
  nshell = chkpt_rd_nshell();
44
 
  stype = chkpt_rd_stype();
45
 
  snuc = chkpt_rd_snuc();
46
 
  u = chkpt_rd_usotao();
47
 
  nirreps = chkpt_rd_nirreps();
48
 
  clsdpi = chkpt_rd_clsdpi();
49
 
  openpi = chkpt_rd_openpi();
50
 
  orbspi = chkpt_rd_orbspi();
51
 
  C = chkpt_rd_scf();
52
 
  evals = chkpt_rd_evals();
53
 
  chkpt_close();
54
 
 
55
 
  /* A couple of error traps */
56
 
  if(nirreps != 1) {
57
 
    fprintf(outfile, "\n\tError: localization is only valid in C1 symmetry!\n");
58
 
    exit(PSI_RETURN_FAILURE);
59
 
  }
60
 
  if(openpi[0]) {
61
 
    fprintf(outfile, "\n\tError: localization available for closed-shells only!\n");
62
 
    exit(PSI_RETURN_FAILURE);
63
 
  }
64
 
 
65
 
  /* Frozen orbital info */
66
 
  frdocc = get_frzcpi();
67
 
  nfzc = frdocc[0];
68
 
  free(frdocc);
69
 
 
70
 
  /* Compute the length of each AM block */
71
 
  ip_boolean("PUREAM", &(puream), 0);
72
 
  l_length = init_int_array(LIBINT_MAX_AM);
73
 
  l_length[0] = 1;
74
 
  for(l=1; l < (LIBINT_MAX_AM); l++) {
75
 
    if(puream) l_length[l] = 2 * l + 1;
76
 
    else l_length[l] = l_length[l-1] + l + 1;
77
 
  }
78
 
 
79
 
  /* Set up the atom->AO and AO->atom lookup arrays */
80
 
  aostart = init_int_array(natom);
81
 
  aostop = init_int_array(natom);
82
 
  for(i=0,atom=-1,offset=0; i < nshell; i++) {
83
 
    am = stype[i] - 1;
84
 
    shell_length = l_length[am];
85
 
 
86
 
    if(atom != snuc[i]-1) {
87
 
      if(atom != -1) aostop[atom] = offset-1;
88
 
      atom = snuc[i]-1;
89
 
      aostart[atom] = offset;
90
 
    }
91
 
 
92
 
    offset += shell_length;
93
 
  }
94
 
  aostop[atom] = offset-1;
95
 
 
96
 
  ao2atom = init_int_array(nso);
97
 
  for(i=0; i < natom; i++)
98
 
    for(j=aostart[i]; j <= aostop[i]; j++) ao2atom[j] = i;
99
 
 
100
 
  /* Get the overlap integrals -- these should be identical to AO S */
101
 
  noei = nso*(nso+1)/2;
102
 
  ss = init_array(noei);
103
 
  stat = iwl_rdone(PSIF_OEI,PSIF_SO_S,ss,noei,0,0,outfile);
104
 
  S = block_matrix(nso,nso);
105
 
  for(i=0,ij=0; i < nso; i++)
106
 
    for(j=0; j <= i; j++,ij++) {
107
 
      S[i][j] = S[j][i] = ss[ij];
108
 
    }
109
 
  free(ss);
110
 
 
111
 
  /* Compute nocc --- closed-shells only */
112
 
  for(i=0,nocc=0; i < nirreps; i++) nocc += clsdpi[i];
113
 
 
114
 
  fprintf(outfile, "\tNumber of doubly occupied orbitals: %d\n\n", nocc);
115
 
 
116
 
  fprintf(outfile, "\tIter     Pop. Localization   Max. Rotation Angle       Conv\n");
117
 
  fprintf(outfile, "\t------------------------------------------------------------\n");
118
 
 
119
 
  U = block_matrix(nocc, nocc);
120
 
  V = block_matrix(nocc, nocc);
121
 
  for(i=0; i < nocc; i++) V[i][i] = 1.0;
122
 
  VV = block_matrix(nocc, nocc);
123
 
 
124
 
  for(iter=0; iter < 100; iter++) {
125
 
 
126
 
    P = 0.0;
127
 
    for(i=nfzc; i < nocc; i++) {
128
 
      for(A=0; A < natom; A++) {
129
 
        PiiA = 0.0;
130
 
 
131
 
        for(l=aostart[A]; l <= aostop[A]; l++)
132
 
          for(k=0; k < nso; k++) 
133
 
            PiiA += C[k][i] * C[l][i] * S[k][l];
134
 
 
135
 
        P += PiiA * PiiA;
136
 
      }
137
 
    }
138
 
 
139
 
    /* Compute 2x2 rotations for Pipek-Mezey localization */
140
 
    alphamax = 0.0;
141
 
    for(s=nfzc; s < nocc; s++) {
142
 
      for(t=nfzc; t < s; t++) {
143
 
 
144
 
        Ast = Bst = 0.0;
145
 
 
146
 
        for(A=0; A < natom; A++) {
147
 
 
148
 
          Pst = Pss = Ptt = 0.0;
149
 
              
150
 
          for(l=aostart[A]; l <= aostop[A]; l++) {
151
 
            for(k=0; k < nso; k++) {
152
 
              Pst += 0.5 * (C[k][s] * C[l][t] +
153
 
                            C[l][s] * C[k][t]) * S[k][l];
154
 
 
155
 
              Pss += C[k][s] * C[l][s] * S[k][l];
156
 
 
157
 
              Ptt += C[k][t] * C[l][t] * S[k][l];
158
 
            }
159
 
          }
160
 
 
161
 
          Ast += Pst * Pst - 0.25 * (Pss - Ptt) * (Pss - Ptt);
162
 
          Bst += Pst * (Pss - Ptt);
163
 
 
164
 
        } /* A-loop */
165
 
 
166
 
        /* Compute the rotation angle */
167
 
        AB = Ast * Ast + Bst * Bst;
168
 
        if(fabs(AB) > 0.0) {
169
 
          cos4a = -Ast/sqrt(AB);
170
 
          alpha = 0.25 * acos(cos4a) * (Bst > 0 ? 1 : -1);
171
 
        }
172
 
        else alpha = 0.0;
173
 
 
174
 
        /* Keep up with the maximum 2x2 rotation angle */
175
 
        alphamax = (fabs(alpha) > alphamax ? alpha : alphamax);
176
 
 
177
 
        Uss = cos(alpha);
178
 
        Utt = cos(alpha);
179
 
        Ust = sin(alpha);
180
 
        Uts = -Ust;
181
 
 
182
 
        /* Now do the rotation */
183
 
        for(k=0; k < nso; k++) {
184
 
          Cks = C[k][s];
185
 
          Ckt = C[k][t];
186
 
          C[k][s] = Uss * Cks + Ust * Ckt;
187
 
          C[k][t] = Uts * Cks + Utt * Ckt;
188
 
        }
189
 
 
190
 
        zero_mat(U, nocc, nocc);
191
 
        for(i=0; i < nocc; i++) U[i][i] = 1.0;
192
 
 
193
 
        U[s][s] = Uss;
194
 
        U[t][t] = Utt;
195
 
        U[s][t] = Ust;
196
 
        U[t][s] = Uts;
197
 
 
198
 
        zero_mat(VV, nocc, nocc);
199
 
        for(i=0; i < nocc; i++) {
200
 
          for(j=0; j < nocc; j++) {
201
 
            for(k=0; k < nocc; k++) {
202
 
              VV[i][j] += V[i][k] * U[j][k];
203
 
            }
204
 
          }
205
 
        }
206
 
 
207
 
        for(i=0; i < nocc; i++)
208
 
          for(j=0; j < nocc; j++)
209
 
            V[i][j] = VV[i][j];
210
 
              
211
 
      } /* t-loop */
212
 
    } /* s-loop */
213
 
 
214
 
    conv = fabs(alphamax) - fabs(alphalast);
215
 
    fprintf(outfile, "\t%4d  %20.10f  %20.10f  %4.3e\n", iter, P, alphamax, conv);
216
 
    if((iter > 2) && ((fabs(conv) < 1e-12) || alphamax == 0.0)) break;
217
 
    alphalast = alphamax;
218
 
 
219
 
    fflush(outfile);
220
 
      
221
 
  } /* iter-loop */
222
 
 
223
 
  /*  print_mat(V, nocc, nocc, outfile);  */
224
 
 
225
 
  /* Transform occupied orbital eigenvalues */
226
 
  F = block_matrix(nocc, nocc);
227
 
  for(i=0; i < nocc; i++)
228
 
    for(j=0; j < nocc; j++)
229
 
      for(k=0; k < nocc; k++) 
230
 
        F[i][j] += V[k][i] * evals[k] * V[k][j];
231
 
 
232
 
  /*
233
 
    fprintf(outfile, "\nTransformed Orbital Energies:\n");
234
 
    print_mat(F, nocc, nocc, outfile);
235
 
  */
236
 
 
237
 
  /* Compute a reordering array based on the diagonal elements of F */
238
 
  orb_order = init_int_array(nocc);
239
 
  orb_boolean = init_int_array(nocc);
240
 
  for(i=0; i < nocc; i++) { orb_order[i] = 0;  orb_boolean[i] = 0; }
241
 
 
242
 
  for(i=0,max=0; i < nocc; i++) /* First, find the overall maximum */
243
 
    if(fabs(F[i][i]) > fabs(F[max][max])) max = i;
244
 
 
245
 
  orb_order[0] = max;  orb_boolean[max] = 1;
246
 
 
247
 
  for(i=1; i < nocc; i++) {
248
 
    max = 0;
249
 
    while(orb_boolean[max]) max++; /* Find an unused max */
250
 
    for(j=0; j < nocc; j++) 
251
 
      if((fabs(F[j][j]) >= fabs(F[max][max])) && !orb_boolean[j]) max = j;
252
 
    orb_order[i] = max; orb_boolean[max] = 1;
253
 
  }
254
 
 
255
 
  /*
256
 
    for(i=0; i < nocc; i++) fprintf(outfile, "%d %d\n", i, orb_order[i]);
257
 
  */
258
 
 
259
 
  /*
260
 
    fprintf(outfile, "\n\tPipek-Mezey Localized MO's (before sort):\n");
261
 
    print_mat(C, nso, nmo, outfile);
262
 
  */
263
 
 
264
 
  /* Now reorder the localized MO's according to F */
265
 
  Ctmp = block_matrix(nso,nocc);
266
 
  for(i=0; i < nocc; i++)
267
 
    for(j=0; j < nso; j++) Ctmp[j][i] = C[j][i];
268
 
 
269
 
  for(i=0; i < nocc; i++) {
270
 
    iold = orb_order[i];
271
 
    for(j=0; j < nso; j++) C[j][i] = Ctmp[j][iold];
272
 
    evals[i] = F[iold][iold];
273
 
  }
274
 
  free_block(Ctmp);
275
 
 
276
 
  print = 0;
277
 
  errcod = ip_boolean("PRINT_MOS", &(print), 0);
278
 
  if(print) {
279
 
    fprintf(outfile, "\n\tPipek-Mezey Localized MO's (after sort):\n");
280
 
    print_mat(C, nso, nmo, outfile);
281
 
  }
282
 
 
283
 
  /* Check MO normalization */
284
 
  /*
285
 
    for(i=0; i < nmo; i++) {
286
 
    norm = 0.0;
287
 
    for(j=0; j < nso; j++) 
288
 
    for(k=0; k < nso; k++) {
289
 
    norm += C[j][i] * C[k][i] * S[j][k];
290
 
    }
291
 
 
292
 
    fprintf(outfile, "norm[%d] = %20.10f\n", i, norm);
293
 
    }
294
 
  */
295
 
 
296
 
  /* correct orbital phases for amplitude restarts */
297
 
  chkpt_init(PSIO_OPEN_OLD);
298
 
  scf_old = chkpt_rd_local_scf();
299
 
  chkpt_close();
300
 
  if (scf_old != NULL) {
301
 
    MO_S = block_matrix(nmo, nmo);
302
 
    X = block_matrix(nso, nmo);
303
 
    C_DGEMM('n','n',nso, nmo, nso, 1, &(S[0][0]), nso, &(C[0][0]), nmo,
304
 
            0, &(X[0][0]), nmo);
305
 
    C_DGEMM('t','n',nmo, nmo, nso, 1, &(scf_old[0][0]), nmo, &(X[0][0]), nmo,
306
 
            0, &(MO_S[0][0]), nmo);
307
 
    free_block(X);
308
 
 
309
 
    /*
310
 
    fprintf(outfile, "Approximate Overlap Matrix\n");
311
 
    print_mat(MO_S, nmo, nmo, outfile);
312
 
    */
313
 
 
314
 
    for(p=0; p < nmo; p++) {
315
 
      max = 0.0;
316
 
      for(q=0; q < nmo; q++) {
317
 
        if(fabs(MO_S[p][q]) > max) {
318
 
          max = fabs(MO_S[p][q]); max_col = q;
319
 
        }
320
 
      }
321
 
      if(max_col != p) phase_ok = 0;
322
 
    }
323
 
 
324
 
    chkpt_init(PSIO_OPEN_OLD);
325
 
    chkpt_wt_phase_check(phase_ok);
326
 
    chkpt_close();
327
 
    if(phase_ok) {
328
 
      for(p=0; p < nmo; p++) {
329
 
        if(MO_S[p][p] < 0.0) {
330
 
          for(q=0; q < nso; q++)
331
 
            C[q][p] *= -1.0;
332
 
        }
333
 
      }
334
 
    }
335
 
 
336
 
    free_block(MO_S);
337
 
    free_block(scf_old);
338
 
  }
339
 
  free_block(S);
340
 
 
341
 
  /* Write the new MO's to chkpt */
342
 
  chkpt_init(PSIO_OPEN_OLD);
343
 
  chkpt_wt_scf(C);
344
 
  chkpt_wt_local_scf(C);
345
 
  chkpt_close();
346
 
 
347
 
  free_block(C);
348
 
  free(evals);
349
 
 
350
 
  fprintf(outfile, "\n\tLocalization of occupied orbitals complete.\n");
351
 
 
352
 
  exit_io();
353
 
  exit(PSI_RETURN_SUCCESS);
354
 
}
355
 
 
356
 
void init_io(int argc, char * argv[])
357
 
{
358
 
  extern char *gprgid();
359
 
  char *progid;
360
 
 
361
 
  progid = (char *) malloc(strlen(gprgid())+2);
362
 
  sprintf(progid, ":%s",gprgid());
363
 
 
364
 
  psi_start(argc-1,argv+1,0);
365
 
  ip_cwk_add(":INPUT"); /* for checking puream keyword */
366
 
  ip_cwk_add(progid);
367
 
  free(progid);
368
 
  tstart(outfile);
369
 
 
370
 
  psio_init();
371
 
}
372
 
 
373
 
void title(void)
374
 
{
375
 
  fprintf(outfile, "\n");
376
 
  fprintf(outfile, "\t\t\t**************************\n");
377
 
  fprintf(outfile, "\t\t\t*                        *\n");
378
 
  fprintf(outfile, "\t\t\t*          LOCAL         *\n");
379
 
  fprintf(outfile, "\t\t\t*                        *\n");
380
 
  fprintf(outfile, "\t\t\t**************************\n");
381
 
  fprintf(outfile, "\n");
382
 
}
383
 
 
384
 
void exit_io(void)
385
 
{
386
 
  psio_done();
387
 
  tstop(outfile);
388
 
  psi_stop();
389
 
}
390
 
 
391
 
char *gprgid()
392
 
{
393
 
   char *prgid = "LOCAL";
394
 
 
395
 
   return(prgid);
396
 
}