~ubuntu-branches/ubuntu/vivid/psicode/vivid

« back to all changes in this revision

Viewing changes to src/bin/optking/disp_freq_energy_cart.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2008-06-07 16:49:57 UTC
  • mfrom: (2.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080607164957-8pifvb133yjlkagn
Tags: 3.3.0-3
* debian/rules (DEB_MAKE_CHECK_TARGET): Do not abort test suite on
  failures.
* debian/rules (DEB_CONFIGURE_EXTRA_FLAGS): Set ${bindir} to /usr/lib/psi.
* debian/rules (install/psi3): Move psi3 file to /usr/bin.
* debian/patches/07_464867_move_executables.dpatch: New patch, add
  /usr/lib/psi to the $PATH, so that the moved executables are found.
  (closes: #464867)
* debian/patches/00list: Adjusted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* DISP_FREQ_ENERGY_CART makes symmetry-adapted cartesian coordinates and displaces
 
2
   along them to setup frequencies by energy points */
 
3
 
 
4
#if HAVE_CMATH
 
5
# include <cmath>
 
6
#else
 
7
# include <math.h>
 
8
#endif
 
9
 
 
10
extern "C" {
 
11
#include <stdio.h>
 
12
#include <libchkpt/chkpt.h>
 
13
#include <stdlib.h>
 
14
#include <string.h>
 
15
#include <ctype.h>
 
16
#include <libciomr/libciomr.h>
 
17
#include <libqt/qt.h>
 
18
#include <libipv1/ip_lib.h>
 
19
#include <physconst.h>
 
20
#include <libpsio/psio.h>
 
21
#include <psifiles.h>
 
22
}
 
23
 
 
24
#define EXTERN
 
25
#include "opt.h"
 
26
#undef EXTERN
 
27
#include "cartesians.h"
 
28
#include "internals.h"
 
29
#include "salc.h"
 
30
#include "bond_lengths.h"
 
31
 
 
32
extern int get_irrep_xyz( double **cartrep, int xyz);
 
33
extern int check_coordinates(int natom, double *coord, double *masses, double *Zvals,
 
34
    int *ndisp_small, double ***disp_small);
 
35
 
 
36
int disp_freq_energy_cart(cartesians &carts)
 
37
{
 
38
  int i,j,a,b,I,k,dim, ndisp_all, nsalc_all, natom, atom, xyz, cnt, loner, *ndisp;
 
39
  int op, atom2, nirreps, natom_unique, irrep, diag_ind, atom_unique;
 
40
  double *coord, energy, ***disp_orig, **displacements, *character, *disp_e;
 
41
  double *v, *f, *q, *masses, **constraints, normval, dotval, **constraints_ortho, *Zvals;
 
42
  int **ict, print=0,nconstraints, *ua2a;
 
43
  int *nsalc_orig, *nsalc, *irrep_per_disp;
 
44
  double ***geoms, **moi, *v1_A, *v1_B, *big_zeroes;
 
45
  double *com, **X, *evals, tval, tval1, tval2, *disp_grad, **cartrep;
 
46
  double ***salc_orig, ***salc;
 
47
  psio_address next;
 
48
  // print=1;
 
49
 
 
50
  coord = carts.get_coord();
 
51
  energy = carts.get_energy();
 
52
  natom = carts.get_natom();
 
53
  masses = carts.get_mass();
 
54
  Zvals = carts.get_Zvals();
 
55
  nirreps = syminfo.nirreps;
 
56
 
 
57
  chkpt_init(PSIO_OPEN_OLD);
 
58
  natom_unique = chkpt_rd_num_unique_atom();
 
59
  ict = chkpt_rd_ict();
 
60
  ua2a = chkpt_rd_ua2a();
 
61
  cartrep = chkpt_rd_cartrep();
 
62
  chkpt_close();
 
63
 
 
64
  if (print) {
 
65
    fprintf(outfile,"Character table from syminfo\n");
 
66
    for (irrep=0; irrep<nirreps; ++irrep) {
 
67
      for (op=0; op<nirreps; ++op)
 
68
        fprintf(outfile,"%d",syminfo.ct[irrep][op]);
 
69
      fprintf(outfile,"\n");
 
70
    }
 
71
    fprintf(outfile,"Cartesian rep from chkpt\n");
 
72
    print_mat(cartrep,nirreps,9,outfile);
 
73
    fprintf(outfile,"ICT table\n");
 
74
    for (i=0; i<natom; ++i) {
 
75
      for (op=0; op<nirreps; ++op)
 
76
        fprintf(outfile," %d ", ict[op][i]);
 
77
      fprintf(outfile,"\n");
 
78
    }
 
79
  }
 
80
 
 
81
  /**** Make sure center of mass is at origin ****/
 
82
  tval = 0.0;
 
83
  com = init_array(3);
 
84
  for (i=0; i<natom; ++i) {
 
85
    for (xyz=0; xyz<3 ; ++xyz)
 
86
      com[xyz] += masses[3*i+xyz] * coord[3*i+xyz];
 
87
    tval += masses[3*i];
 
88
  }
 
89
  for (xyz=0; xyz<3 ; ++xyz)
 
90
    com[xyz] = com[xyz] / tval;
 
91
 
 
92
  for (i=0; i<natom; ++i)
 
93
    for (xyz=0; xyz<3 ; ++xyz)
 
94
      coord[3*i+xyz] -= com[xyz];
 
95
 
 
96
  if (print) {
 
97
    fprintf(outfile,"\n\nCenter of mass\n");
 
98
    for (xyz=0; xyz<3 ; ++xyz)
 
99
      fprintf(outfile,"%15.10lf", com[xyz]);
 
100
    fprintf(outfile,"\n\nNew Geometry wrt COM\n");
 
101
    for (i=0; i<natom; ++i)
 
102
      fprintf(outfile,"%15.10lf%15.10lf%15.10lf\n",coord[3*i],coord[3*i+1],coord[3*i+2]);
 
103
    fflush(outfile);
 
104
  }
 
105
  free(com);
 
106
 
 
107
  /**** Determine the rotational coordinates from MOI tensor ****/
 
108
  moi = block_matrix(3,3);
 
109
  for (i=0; i<natom; ++i) {
 
110
    moi[0][0] += masses[3*i] * (SQR(coord[3*i+1]) + SQR(coord[3*i+2]));
 
111
    moi[1][1] += masses[3*i] * (SQR(coord[3*i+0]) + SQR(coord[3*i+2]));
 
112
    moi[2][2] += masses[3*i] * (SQR(coord[3*i+0]) + SQR(coord[3*i+1]));
 
113
    moi[0][1] -= masses[3*i] * coord[3*i+0] * coord[3*i+1];
 
114
    moi[0][2] -= masses[3*i] * coord[3*i+0] * coord[3*i+2];
 
115
    moi[1][2] -= masses[3*i] * coord[3*i+1] * coord[3*i+2];
 
116
  }
 
117
  moi[1][0] = moi[0][1];
 
118
  moi[2][0] = moi[0][2];
 
119
  moi[2][1] = moi[1][2];
 
120
 
 
121
  X = block_matrix(3,3);
 
122
  evals = init_array(3);
 
123
  sq_rsp(3,3,moi,evals,1,X,1.0E-14);
 
124
  free_block(moi);
 
125
  if (print) {
 
126
    fprintf(outfile,"Eigenvectors (X) of MOI tensor\n");
 
127
    print_mat(X,3,3,outfile);
 
128
  }
 
129
 
 
130
  /**** Build matrix with COM and rotational constraints as rows ****/
 
131
  constraints = block_matrix(6, 3*natom);
 
132
  /* COM constraints */
 
133
  for (i=0; i<natom; ++i) {
 
134
    constraints[0][3*i]   = 1.0 * sqrt(masses[3*i]);
 
135
    constraints[1][3*i+1] = 1.0 * sqrt(masses[3*i+1]);
 
136
    constraints[2][3*i+2] = 1.0 * sqrt(masses[3*i+2]);
 
137
  }
 
138
  /* Rotational constraints */
 
139
  for (i=0; i<natom; ++i) {
 
140
    tval1 = (coord[3*i+0] * X[0][1]) + (coord[3*i+1] * X[1][1]) + (coord[3*i+2] * X[2][1]);
 
141
    tval2 = (coord[3*i+0] * X[0][2]) + (coord[3*i+1] * X[1][2]) + (coord[3*i+2] * X[2][2]);
 
142
    for (xyz = 0; xyz < 3; ++xyz)
 
143
      constraints[3][3*i+xyz] = (tval1 * X[xyz][2] - tval2 * X[xyz][1]) * sqrt(masses[3*i]);
 
144
  }
 
145
  for (i=0; i<natom; ++i) {
 
146
    tval1 = (coord[3*i+0] * X[0][2]) + (coord[3*i+1] * X[1][2]) + (coord[3*i+2] * X[2][2]);
 
147
    tval2 = (coord[3*i+0] * X[0][0]) + (coord[3*i+1] * X[1][0]) + (coord[3*i+2] * X[2][0]);
 
148
    for (xyz = 0; xyz < 3; ++xyz)
 
149
      constraints[4][3*i+xyz] = (tval1 * X[xyz][0] - tval2 * X[xyz][2]) * sqrt(masses[3*i]);
 
150
  }
 
151
  for (i=0; i<natom; ++i) {
 
152
    tval1 = (coord[3*i+0] * X[0][0]) + (coord[3*i+1] * X[1][0]) + (coord[3*i+2] * X[2][0]);
 
153
    tval2 = (coord[3*i+0] * X[0][1]) + (coord[3*i+1] * X[1][1]) + (coord[3*i+2] * X[2][1]);
 
154
    for (xyz = 0; xyz < 3; ++xyz)
 
155
      constraints[5][3*i+xyz] = (tval1 * X[xyz][1] - tval2 * X[xyz][0]) * sqrt(masses[3*i]);
 
156
  }
 
157
  if (print) {
 
158
    fprintf(outfile,"Raw COM/Rotational Constraints\n");
 
159
    print_mat(constraints,6,3*natom,outfile);
 
160
  }
 
161
  free_block(X);
 
162
 
 
163
  /* Remove NULL constraint (if present) and normalize rest of them */
 
164
  cnt = -1;
 
165
  for (i = 0; i < 6; ++i) {
 
166
    dot_arr(constraints[i], constraints[i], 3*natom, &normval);
 
167
    if (normval > 1.0E-10) {
 
168
      ++cnt;
 
169
      for (j=0; j<3*natom; ++j)
 
170
        constraints[cnt][j] = constraints[i][j] / sqrt(normval) ;
 
171
    }
 
172
  }
 
173
  nconstraints = cnt+1;
 
174
  /*
 
175
  if (print) {
 
176
    fprintf(outfile,"Normalized constraints\n");
 
177
    print_mat(constraints,nconstraints,3*natom,outfile);
 
178
  }
 
179
  */
 
180
 
 
181
  /* Orthogonalize rotations and translations exactly-is this ever necessary?*/
 
182
  constraints_ortho = block_matrix(nconstraints,3*natom);
 
183
  cnt = 0;
 
184
  for (i=0; i<nconstraints; ++i)
 
185
    cnt += schmidt_add(constraints_ortho, cnt, 3*natom, constraints[i]);
 
186
  for (i=0; i<nconstraints; ++i)
 
187
    for (j=0; j<3*natom; ++j)
 
188
      constraints[i][j] = constraints_ortho[i][j];
 
189
  free_block(constraints_ortho);
 
190
  /*
 
191
  if (print) {
 
192
    fprintf(outfile,"Orthogonal constraints\n");
 
193
    print_mat(constraints,nconstraints,3*natom,outfile);
 
194
  }
 
195
  */
 
196
 
 
197
  /**** Form symmetry-adapted cartesian vectors ****/
 
198
  salc_orig = (double ***) malloc(nirreps*sizeof(double **));
 
199
  nsalc_orig = init_int_array(nirreps);
 
200
 
 
201
  /* loop over irrep of coordinates */
 
202
  for (irrep=0; irrep < nirreps; ++irrep) {
 
203
    salc_orig[irrep] = block_matrix(3*natom,3*natom);
 
204
    cnt=-1;
 
205
 
 
206
    /* loop over unique atoms and xyz coordinates */
 
207
    for (atom_unique=0; atom_unique < natom_unique; ++atom_unique) {
 
208
      atom = ua2a[atom_unique];
 
209
      /* determine if atom is loner, having no symmetry-related partners */
 
210
      loner = 1;
 
211
      for (op=0; op < nirreps; ++op) { 
 
212
        if (atom != ict[op][atom] - 1)
 
213
         loner = 0;
 
214
      }
 
215
 
 
216
      for (xyz=0; xyz<3; ++xyz) {
 
217
        ++cnt;
 
218
        /* if a loner, don't try to adapt */
 
219
        if (loner) {
 
220
          if ( get_irrep_xyz( cartrep, xyz ) == irrep) {
 
221
            salc_orig[irrep][cnt][3*atom+xyz] = 1.0;
 
222
          }
 
223
        }
 
224
        else {
 
225
          diag_ind = xyz*3 + xyz;
 
226
          for (op=0; op < nirreps; ++op) { 
 
227
            atom2 = ict[op][atom] - 1;
 
228
            for (i=0; i<3*natom; ++i)
 
229
              salc_orig[irrep][cnt][3*atom2+xyz] += cartrep[op][diag_ind] / syminfo.ct[irrep][op];
 
230
          }
 
231
        }
 
232
      }
 
233
    }
 
234
    nsalc_orig[irrep] = cnt+1;
 
235
  }
 
236
  if (print) {
 
237
    for (irrep=0; irrep < nirreps; ++irrep) {
 
238
      fprintf(outfile,"Cartesian SALCs for Irrep %d\n", irrep);
 
239
      print_mat(salc_orig[irrep], nsalc_orig[irrep], 3*natom, outfile);
 
240
    }
 
241
  }
 
242
 
 
243
  /**** Schmidt orthogonalize coordinates to remove COM/ROT constraints ****/
 
244
  salc = (double ***) malloc(nirreps*sizeof(double **));
 
245
  nsalc = init_int_array(nirreps);
 
246
  v = init_array(3*natom);
 
247
  nsalc_all = 0;
 
248
  for (irrep=0; irrep< nirreps; ++irrep) {
 
249
    salc[irrep] = block_matrix(nsalc_orig[irrep],3*natom);
 
250
    cnt = 0;
 
251
 
 
252
    for (i=0; i<nsalc_orig[irrep]; ++i) {
 
253
      zero_arr(v,3*natom);
 
254
 
 
255
      for (I=0; I<3*natom; I++)
 
256
        v[I] = salc_orig[irrep][i][I];
 
257
 
 
258
      for (j=0; j<nconstraints; j++) {
 
259
        dot_arr(salc_orig[irrep][i], constraints[j], 3*natom, &dotval) ;
 
260
        for (I=0; I<3*natom; I++)
 
261
          v[I] -= dotval * constraints[j][I] ;
 
262
      }
 
263
 
 
264
      dot_arr(v, v, 3*natom, &normval);
 
265
      if (normval > 1.0E-10) {
 
266
        for (j=0; j<3*natom; ++j)
 
267
          v[j] = v[j] / sqrt(normval) ;
 
268
  
 
269
        cnt += schmidt_add(salc[irrep], cnt, 3*natom, v);
 
270
      }
 
271
    }
 
272
    nsalc[irrep] = cnt;
 
273
    nsalc_all += cnt;
 
274
  }
 
275
  for (irrep=0; irrep<nirreps; ++irrep) {
 
276
    free_block(salc_orig[irrep]);
 
277
  }
 
278
  free_block(constraints);
 
279
  free(nsalc_orig);
 
280
  free(v);
 
281
 
 
282
  if (optinfo.freq_irrep != -1) {
 
283
    for (irrep=0; irrep < nirreps; ++irrep)
 
284
      if (irrep != (optinfo.freq_irrep - 1) ) {
 
285
        nsalc_all -= nsalc[irrep];
 
286
        nsalc[irrep] = 0;
 
287
      }
 
288
  }
 
289
 
 
290
  if (print) {
 
291
    for (irrep=0; irrep < nirreps; ++irrep)
 
292
      if (nsalc[irrep]) {
 
293
        fprintf(outfile,"Projected Cartesian Displacements, irrep %d\n", irrep);
 
294
        print_mat(salc[irrep], nsalc[irrep], 3*natom, outfile);
 
295
      }
 
296
  }
 
297
 
 
298
  check_coordinates(natom,coord,masses,Zvals,nsalc,salc);
 
299
 
 
300
  /* determine number of displacements */
 
301
  /* 1/h^2 * (f(1,0) + f(-1,0) + 2f(0,0) ) */
 
302
  ndisp_all = 0;
 
303
  ndisp = init_int_array(nirreps);
 
304
  for (irrep=0; irrep<nirreps; ++irrep) {
 
305
 
 
306
    /* diagonal displacements */
 
307
    if (irrep == 0) {
 
308
      if (optinfo.points == 3)
 
309
        ndisp[irrep] = 2 * nsalc[irrep];
 
310
      else if (optinfo.points == 5)
 
311
        ndisp[irrep] = 4 * nsalc[irrep];
 
312
    }
 
313
    else {
 
314
      if (optinfo.points == 3)
 
315
        ndisp[irrep] = nsalc[irrep];
 
316
      else if (optinfo.points == 5)
 
317
        ndisp[irrep] = 2* nsalc[irrep];
 
318
    }
 
319
 
 
320
    /* off-diagonal displacements */
 
321
    if (optinfo.points == 3)
 
322
      ndisp[irrep] += 4 * nsalc[irrep] * (nsalc[irrep] - 1) / 2;
 
323
    else if (optinfo.points == 5)
 
324
      ndisp[irrep] += 16 * nsalc[irrep] * (nsalc[irrep] - 1) / 2;
 
325
 
 
326
    ndisp_all += ndisp[irrep];
 
327
  }
 
328
 
 
329
  for (irrep=0; irrep<nirreps;++irrep)
 
330
    fprintf(outfile,"ndisp[%d]: %d\n",irrep,ndisp[irrep]);
 
331
  fflush(outfile);
 
332
 
 
333
  /*** construct displaced geometries ***/
 
334
  geoms = (double ***) malloc(nirreps*sizeof(double **));
 
335
  for (irrep=0; irrep<nirreps; ++irrep) {
 
336
 
 
337
    geoms[irrep] = block_matrix(ndisp[irrep],3*natom);
 
338
    for (i=0; i<ndisp[irrep]; ++i)
 
339
      for (j=0; j<3*natom; ++j)
 
340
        geoms[irrep][i][j] = coord[j];
 
341
 
 
342
    /* construct diagonal displacements */
 
343
    if (irrep == 0) {
 
344
      cnt = 0;
 
345
      for (i=0; i<nsalc[irrep]; ++i) {
 
346
        if (optinfo.points == 3) {
 
347
          for (j=0; j < 3*natom; ++j) {
 
348
            geoms[irrep][cnt+0][j] -= optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
349
            geoms[irrep][cnt+1][j] += optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
350
          }
 
351
          cnt += 2;
 
352
        }
 
353
        else if (optinfo.points == 5) {
 
354
          for (j=0; j < 3*natom; ++j) {
 
355
            geoms[irrep][cnt+0][j] -= 2.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
356
            geoms[irrep][cnt+1][j] -= 1.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
357
            geoms[irrep][cnt+2][j] += 1.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
358
            geoms[irrep][cnt+3][j] += 2.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
359
          }
 
360
          cnt += 4;
 
361
        }
 
362
      }
 
363
    }
 
364
    else { /* asymmetric diagonal displacements */
 
365
      cnt = 0;
 
366
      for (i=0; i<nsalc[irrep]; ++i) {
 
367
        if (optinfo.points == 3) {
 
368
          for (j=0; j < 3*natom; ++j)
 
369
            geoms[irrep][cnt][j]   -= optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
370
          cnt += 1;
 
371
        }
 
372
        else if (optinfo.points == 5) {
 
373
          for (j=0; j < 3*natom; ++j) {
 
374
            geoms[irrep][cnt+0][j] -= 2.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
375
            geoms[irrep][cnt+1][j] -= 1.0 * optinfo.disp_size * salc[irrep][i][j] / sqrt(masses[j]);
 
376
          }
 
377
          cnt += 2;
 
378
        }
 
379
      }
 
380
    }
 
381
    /* add off-diagonal displacements */
 
382
 
 
383
    for (i=0; i<nsalc[irrep]; ++i) {
 
384
      for (j=i+1; j<nsalc[irrep]; ++j) {
 
385
        if (optinfo.points == 3) {
 
386
          for (k=0; k < 3*natom; ++k) {
 
387
            geoms[irrep][cnt+0][k] += ( + salc[irrep][i][k] + salc[irrep][j][k] )
 
388
              * optinfo.disp_size / sqrt(masses[k]);
 
389
            geoms[irrep][cnt+1][k] += ( + salc[irrep][i][k] - salc[irrep][j][k] )
 
390
              * optinfo.disp_size / sqrt(masses[k]);
 
391
            geoms[irrep][cnt+2][k] += ( - salc[irrep][i][k] + salc[irrep][j][k] )
 
392
              * optinfo.disp_size / sqrt(masses[k]);
 
393
            geoms[irrep][cnt+3][k] += ( - salc[irrep][i][k] - salc[irrep][j][k] )
 
394
              * optinfo.disp_size / sqrt(masses[k]);
 
395
          }
 
396
          cnt += 4;
 
397
        }
 
398
        else if (optinfo.points == 5) {
 
399
          for (k=0; k < 3*natom; ++k) {
 
400
            geoms[irrep][cnt+0][k] += ( - 2.0 * salc[irrep][i][k] - 2.0 * salc[irrep][j][k] )
 
401
              * optinfo.disp_size / sqrt(masses[k]);
 
402
            geoms[irrep][cnt+1][k] += ( - 1.0 * salc[irrep][i][k] - 2.0 * salc[irrep][j][k] )
 
403
              * optinfo.disp_size / sqrt(masses[k]);
 
404
            geoms[irrep][cnt+2][k] += ( + 1.0 * salc[irrep][i][k] - 2.0 * salc[irrep][j][k] )
 
405
              * optinfo.disp_size / sqrt(masses[k]);
 
406
            geoms[irrep][cnt+3][k] += ( + 2.0 * salc[irrep][i][k] - 2.0 * salc[irrep][j][k] )
 
407
              * optinfo.disp_size / sqrt(masses[k]);
 
408
            geoms[irrep][cnt+4][k] += ( - 2.0 * salc[irrep][i][k] - 1.0 * salc[irrep][j][k] )
 
409
              * optinfo.disp_size / sqrt(masses[k]);
 
410
            geoms[irrep][cnt+5][k] += ( - 1.0 * salc[irrep][i][k] - 1.0 * salc[irrep][j][k] )
 
411
              * optinfo.disp_size / sqrt(masses[k]);
 
412
            geoms[irrep][cnt+6][k] += ( + 1.0 * salc[irrep][i][k] - 1.0 * salc[irrep][j][k] )
 
413
              * optinfo.disp_size / sqrt(masses[k]);
 
414
            geoms[irrep][cnt+7][k] += ( + 2.0 * salc[irrep][i][k] - 1.0 * salc[irrep][j][k] )
 
415
              * optinfo.disp_size / sqrt(masses[k]);
 
416
            geoms[irrep][cnt+8][k] += ( - 2.0 * salc[irrep][i][k] + 1.0 * salc[irrep][j][k] )
 
417
              * optinfo.disp_size / sqrt(masses[k]);
 
418
            geoms[irrep][cnt+9][k] += ( - 1.0 * salc[irrep][i][k] + 1.0 * salc[irrep][j][k] )
 
419
              * optinfo.disp_size / sqrt(masses[k]);
 
420
            geoms[irrep][cnt+10][k] += ( + 1.0 * salc[irrep][i][k] + 1.0 * salc[irrep][j][k] )
 
421
              * optinfo.disp_size / sqrt(masses[k]);
 
422
            geoms[irrep][cnt+11][k] += ( + 2.0 * salc[irrep][i][k] + 1.0 * salc[irrep][j][k] )
 
423
              * optinfo.disp_size / sqrt(masses[k]);
 
424
            geoms[irrep][cnt+12][k] += ( - 2.0 * salc[irrep][i][k] + 2.0 * salc[irrep][j][k] )
 
425
              * optinfo.disp_size / sqrt(masses[k]);
 
426
            geoms[irrep][cnt+13][k] += ( - 1.0 * salc[irrep][i][k] + 2.0 * salc[irrep][j][k] )
 
427
              * optinfo.disp_size / sqrt(masses[k]);
 
428
            geoms[irrep][cnt+14][k] += ( + 1.0 * salc[irrep][i][k] + 2.0 * salc[irrep][j][k] )
 
429
              * optinfo.disp_size / sqrt(masses[k]);
 
430
            geoms[irrep][cnt+15][k] += ( + 2.0 * salc[irrep][i][k] + 2.0 * salc[irrep][j][k] )
 
431
              * optinfo.disp_size / sqrt(masses[k]);
 
432
          }
 
433
          cnt += 16;
 
434
        }
 
435
      }
 
436
    }
 
437
  }
 
438
  free(masses);
 
439
 
 
440
  /**** write out info to PSIF_OPTKING, geoms and coordinates in irrep order ****/
 
441
  open_PSIF();
 
442
 
 
443
  big_zeroes = init_array(ndisp_all*3*natom);
 
444
  psio_write_entry(PSIF_OPTKING, "OPT: Displaced geometries", (char *) &(big_zeroes[0]),
 
445
      ndisp_all*3*natom*sizeof(double));
 
446
  psio_write_entry(PSIF_OPTKING, "OPT: Adapted cartesians", (char *) &(big_zeroes[0]),
 
447
      ndisp_all*3*natom*sizeof(double));
 
448
  psio_write_entry(PSIF_OPTKING, "OPT: Displaced gradients", (char *) &(big_zeroes[0]),
 
449
      ndisp_all*3*natom*sizeof(double));
 
450
  free(big_zeroes);
 
451
 
 
452
  next = PSIO_ZERO;
 
453
  for (irrep=0; irrep<nirreps; ++irrep) {
 
454
    if (ndisp[irrep]) {
 
455
      psio_write(PSIF_OPTKING, "OPT: Displaced geometries",
 
456
          (char *) &(geoms[irrep][0][0]), ndisp[irrep]*3*natom*sizeof(double), next, &next);
 
457
fprintf(outfile,"Displaced Geometries of irrep %d.\n",irrep);
 
458
print_mat(geoms[irrep],ndisp[irrep],3*natom,outfile);
 
459
    }
 
460
    free_block(geoms[irrep]);
 
461
  }
 
462
  free(geoms);
 
463
 
 
464
  next = PSIO_ZERO;
 
465
  for (irrep=0; irrep<nirreps; ++irrep) {
 
466
    if (nsalc[irrep]) {
 
467
      psio_write(PSIF_OPTKING, "OPT: Adapted cartesians", (char *) &(salc[irrep][0][0]),
 
468
      nsalc[irrep]*3*natom*sizeof(double), next, &next);
 
469
    }
 
470
    free_block(salc[irrep]);
 
471
  }
 
472
  free(salc);
 
473
 
 
474
  /* make list of irreps for each disp used to make prefixes */
 
475
  irrep_per_disp = (int *) malloc(ndisp_all*sizeof(int));
 
476
  cnt = -1;
 
477
  for (irrep=0; irrep<nirreps; ++irrep) {
 
478
    for (i=0; i<ndisp[irrep]; ++i)
 
479
      irrep_per_disp[++cnt] = irrep;
 
480
  }
 
481
  fprintf(outfile,"Irreps per disp: ");
 
482
  for (i=0; i<ndisp_all; ++i)
 
483
    fprintf(outfile,"%d ",irrep_per_disp[i]);
 
484
  fprintf(outfile,"\n");
 
485
 
 
486
  /**** Write parameters to PSIO file ****/
 
487
  optinfo.disp_num = 0;
 
488
  disp_e = init_array(ndisp_all);
 
489
  optinfo.micro_iteration = 0;
 
490
 
 
491
  /*
 
492
  ndisp_all = 8;
 
493
  ndisp[1] = 0;
 
494
  ndisp[2] = 0;
 
495
  ndisp[3] = 0;
 
496
  nsalc_all = 4;
 
497
  nsalc[1] = 0;
 
498
  nsalc[2] = 0;
 
499
  nsalc[3] = 0;
 
500
  */
 
501
 
 
502
  psio_write_entry(PSIF_OPTKING, "OPT: Displaced energies",
 
503
      (char *) &(disp_e[0]), ndisp_all*sizeof(double));
 
504
  psio_write_entry(PSIF_OPTKING, "OPT: Reference geometry",
 
505
      (char *) &(coord[0]), 3*natom*sizeof(double));
 
506
  psio_write_entry(PSIF_OPTKING, "OPT: Reference energy",
 
507
      (char *) &(energy), sizeof(double));
 
508
  psio_write_entry(PSIF_OPTKING, "OPT: Current disp_num",
 
509
      (char *) &(optinfo.disp_num),sizeof(int));
 
510
  psio_write_entry(PSIF_OPTKING, "OPT: Num. of disp.",
 
511
      (char *) &(ndisp_all), sizeof(int));
 
512
  psio_write_entry(PSIF_OPTKING, "OPT: Disp. per irrep",
 
513
      (char *) &(ndisp[0]), nirreps*sizeof(int));
 
514
  psio_write_entry(PSIF_OPTKING, "OPT: Irrep per disp",
 
515
      (char *) &(irrep_per_disp[0]), ndisp_all*sizeof(int));
 
516
  psio_write_entry(PSIF_OPTKING, "OPT: Num. of coord.",
 
517
      (char *) &(nsalc_all), sizeof(int));
 
518
  psio_write_entry(PSIF_OPTKING, "OPT: Coord. per irrep",
 
519
      (char *) &(nsalc[0]), nirreps*sizeof(int));
 
520
  psio_write_entry(PSIF_OPTKING, "Micro_iteration",
 
521
      (char *) &(optinfo.micro_iteration),sizeof(int));
 
522
  close_PSIF();
 
523
 
 
524
  for (irrep=0; irrep<nirreps; ++irrep)
 
525
    fprintf(outfile,"Number of %s displaced geometries is %d.\n",syminfo.irrep_lbls[irrep],ndisp[irrep]);
 
526
  fprintf(outfile,"Total number of displaced geometries is %d.\n",ndisp_all);
 
527
 
 
528
  free(nsalc);
 
529
  free(ndisp);
 
530
  free(coord);
 
531
  free(disp_e);
 
532
  free(ua2a);
 
533
  return(ndisp_all);
 
534
}
 
535