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

« back to all changes in this revision

Viewing changes to src/bin/detcas/hessian.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 <stdlib.h>
2
 
#include <stdio.h>
3
 
#include <libipv1/ip_lib.h>
4
 
#include <libciomr/libciomr.h>
5
 
#include <libqt/qt.h>
6
 
#include "globaldefs.h"
7
 
#include "globals.h"
8
 
 
9
 
/*
10
 
** form_appx_diag_mo_hess
11
 
**
12
 
** Calculates the approximate diagonal MO Hessian according to
13
 
** G. Chaban, M. W. Schmidt, and M. S. Gordon, Theor. Chem. Acc.,
14
 
** 97, 88-95 (1997)
15
 
** 
16
 
** Also uses active-active formulae from G. Chaban, personal communication
17
 
** (derived from H. J. Aa. Jensen and H. Agren, Chem. Phys. 104, 229 (1986))
18
 
**
19
 
** I am assuming that the pairs (p,q) are always given such that p>=q
20
 
**
21
 
** C. David Sherrill
22
 
** April 1998
23
 
** 
24
 
** Updated with active-active parts, March 2004
25
 
*/
26
 
void form_appx_diag_mo_hess(int npairs, int *ppair, int *qpair, 
27
 
  double *F_core, double *tei, double **opdm, double *tpdm, double *F_act,
28
 
  int firstact, int lastact, double *hess)
29
 
{
30
 
 
31
 
  int pair, p, q, pq, pp, qq;
32
 
  int ia;
33
 
  int i,ii,a,aa,t,tt,u,tu,v,w,vw,uv,tuvw;
34
 
  int qv,puvw,quvw,pv,pu,qu,pupv,quqv,ppuv,qquv,pvqu,puqv,pquv;
35
 
  double value;
36
 
 
37
 
  fprintf(outfile, "Forming approximate diagonal orbital Hessian\n");
38
 
 
39
 
  /* loop over the independent pairs */
40
 
  for (pair=0; pair<npairs; pair++) {
41
 
    p = ppair[pair];
42
 
    q = qpair[pair];
43
 
    pq = ioff[p] + q;
44
 
    pp = ioff[p] + p;
45
 
    qq = ioff[q] + q;
46
 
  
47
 
    /* H_{ai,ai}, i.e., inactive virt/inactive occ */
48
 
    if (p >= lastact && q < firstact) {
49
 
      hess[pair] = 4.0 * (F_core[pp] + F_act[pp] - F_core[qq] - F_act[qq]);
50
 
    }
51
 
 
52
 
    /* H_{at,at}, i.e., inactive virt with active orb */
53
 
    else if (p >= lastact && q >= firstact) {
54
 
      a = p;  t = q;
55
 
      aa = ioff[a] + a;
56
 
 
57
 
      hess[pair] = 2.0 * opdm[t][t] * (F_core[aa] + F_act[aa]);
58
 
 
59
 
      value = 0.0;
60
 
      for (u=firstact; u<lastact; u++) {
61
 
        tu = INDEX(t,u);
62
 
        value += opdm[t][u] * F_core[tu];
63
 
      }
64
 
      hess[pair] -= 2.0 * value;
65
 
 
66
 
      value = 0.0;
67
 
      for (u=firstact; u<lastact; u++) {
68
 
        tu = INDEX(t,u);
69
 
 
70
 
        /* loop over active v,w ... later restrict to symmetry allowed */
71
 
        for (v=firstact; v<lastact; v++) {
72
 
          for (w=firstact; w<lastact; w++) {
73
 
            vw = INDEX(v,w);
74
 
            tuvw = INDEX(tu,vw); 
75
 
            value += tpdm[tuvw] * tei[tuvw];
76
 
          }
77
 
        }
78
 
         
79
 
      }
80
 
      hess[pair] -= 2.0 * value; 
81
 
       
82
 
    } 
83
 
 
84
 
    /* H_{ti,ti}, i.e., active orb with inactive occ */
85
 
    else if (p >= firstact && q < firstact) {
86
 
      t = p;  i = q;
87
 
      tt = ioff[t] + t;
88
 
      ii = ioff[i] + i; 
89
 
      
90
 
      hess[pair] = 2.0 * opdm[t][t] * (F_core[ii] + F_act[ii]);
91
 
      hess[pair] += 4.0 * (F_core[tt] + F_act[tt] - F_core[ii] - F_act[ii]);
92
 
 
93
 
      value = 0.0;
94
 
      for (u=firstact; u<lastact; u++) {
95
 
        tu = INDEX(t,u);
96
 
        value += opdm[t][u] * F_core[tu];
97
 
      }
98
 
      hess[pair] -= 2.0 * value;
99
 
 
100
 
      value = 0.0;
101
 
      for (u=firstact; u<lastact; u++) {
102
 
        tu = INDEX(t,u);
103
 
 
104
 
        /* loop over active v,w ... later restrict to symmetry allowed */
105
 
        for (v=firstact; v<lastact; v++) {
106
 
          for (w=firstact; w<lastact; w++) {
107
 
            vw = INDEX(v,w);
108
 
            tuvw = INDEX(tu,vw); 
109
 
            value += tpdm[tuvw] * tei[tuvw];
110
 
          }
111
 
        }
112
 
         
113
 
      }
114
 
      hess[pair] -= 2.0 * value; 
115
 
    }
116
 
 
117
 
    /* 
118
 
       H_{t1t2,t1t2}, i.e., active-active (happens for MCSCF, not CASSCF)
119
 
       expression given by personal communication from Galina Chaban,
120
 
       derived from H. J. Aa. Jensen, H. Agren, Chem. Phys. 104, 229 (1982),
121
 
       appendix A.
122
 
    */
123
 
    else if (p >= firstact && q < lastact) {
124
 
      hess[pair] = 2.0 * (  opdm[q][q] * F_core[pp]   
125
 
                          + opdm[p][p] * F_core[qq]
126
 
                          - 2.0 * opdm[p][q] * F_core[pq] );
127
 
      value = 0.0;
128
 
      for (u=firstact; u<lastact; u++) {
129
 
        pu = INDEX(p,u);
130
 
        qu = INDEX(q,u);
131
 
        value += opdm[p][u] * F_core[pu] + opdm[q][u] * F_core[qu];
132
 
        /* should be able to reduce work below by factor of 2 */
133
 
        for (w=firstact; w<lastact; w++) {
134
 
          for (v=firstact; v<lastact; v++) {
135
 
          vw = INDEX(v,w);
136
 
          puvw = INDEX(pu,vw);
137
 
          quvw = INDEX(qu,vw);
138
 
          value += tpdm[puvw] * tei[puvw];
139
 
          value += tpdm[quvw] * tei[quvw]; 
140
 
          }
141
 
        }
142
 
      } 
143
 
      hess[pair] -= value * 2.0;
144
 
 
145
 
      value = 0.0;
146
 
      for (u=firstact; u<lastact; u++) {
147
 
        pu = INDEX(p,u);
148
 
        qu = INDEX(q,u);
149
 
        for (v=firstact; v<lastact; v++) {
150
 
          pv = INDEX(p,v);
151
 
          qv = INDEX(q,v);
152
 
          uv = INDEX(u,v);
153
 
          pupv = INDEX(pu,pv);
154
 
          quqv = INDEX(qu,qv);
155
 
          value += 2.0 * tpdm[pupv] * tei[quqv];
156
 
          value += 2.0 * tpdm[quqv] * tei[pupv]; 
157
 
          ppuv = INDEX(pp,uv);
158
 
          qquv = INDEX(qq,uv);
159
 
          value += tpdm[ppuv] * tei[qquv] + tpdm[qquv] * tei[ppuv];
160
 
          pvqu = INDEX(pv,qu);
161
 
          puqv = INDEX(pu,qv);
162
 
          value -= 4.0 * tpdm[pvqu] * tei[puqv];
163
 
          pquv = INDEX(pq,uv);
164
 
          value -= 2.0 * tpdm[pquv] * tei[pquv];
165
 
        }
166
 
      }
167
 
      hess[pair] += 2.0 * value;
168
 
      if (Params.scale_act_act != 1.0) hess[pair] *= Params.scale_act_act;
169
 
    } /* end case H_{t1t2,t1t2} */
170
 
 
171
 
 
172
 
    else {
173
 
      fprintf(outfile, 
174
 
             "(form_diag_mo_hess): Error, unrecognized class of indep pair\n");
175
 
    }
176
 
 
177
 
  } /* end loop over pairs */
178
 
 
179
 
}
180
 
 
181
 
 
182
 
 
183
 
/*
184
 
** form_diag_mo_hess
185
 
**
186
 
** Calculates the exact diagonal MO Hessian assuming CASSCF
187
 
**
188
 
** See Galina Chaban et al., Theor Chem Acc (1997) 97:88-95
189
 
** and references therein for mathematics of Newton-Raphson
190
 
** approach to MCSCF/CASSCF
191
 
**
192
 
** Supplemented with active-active parts from G. Chaban, personal
193
 
** communication
194
 
**
195
 
** I am assuming that the pairs (p,q) are always given such that p>=q
196
 
**
197
 
** G. O. Hyde
198
 
** January 2002
199
 
**
200
 
** Active-active parts added by C. D. Sherrill, March 2004
201
 
*/
202
 
void form_diag_mo_hess(int npairs, int *ppair, int *qpair, 
203
 
  double *F_core, double *tei, double **opdm, double *tpdm, double *F_act,
204
 
  int firstact, int lastact, double *hess)
205
 
{
206
 
 
207
 
  int pair, p, q, pq, pp, qq, pqpq, ppqq;
208
 
  int i,ii,a,aa,t,tt,u,tu,v,w,vw,tuvw;
209
 
  int au, uv, av, tv, ttuv, aauv, tvtu, avau;
210
 
  int ui, vi, ti, uvii, uivi, uiti, tuii;
211
 
  int qv,puvw,quvw,pv,pu,qu,pupv,quqv,ppuv,qquv,pvqu,puqv,pquv;
212
 
  int delta;
213
 
  double value;
214
 
 
215
 
  fprintf(outfile, "Forming diagonal orbital Hessian\n");
216
 
 
217
 
  /* loop over the independent pairs */
218
 
  for (pair=0; pair<npairs; pair++) {
219
 
    p = ppair[pair];
220
 
    q = qpair[pair];
221
 
    pq = ioff[p] + q;
222
 
    pp = ioff[p] + p;
223
 
    qq = ioff[q] + q;
224
 
    pqpq = ioff[pq] + pq;
225
 
    ppqq = ioff[pp] + qq; 
226
 
 
227
 
    /* H_{ai,ai}, i.e., inactive virt/inactive occ */
228
 
    if (p >= lastact && q < firstact) {
229
 
      hess[pair] = 4.0 * (F_core[pp] + F_act[pp] - F_core[qq] - F_act[qq]
230
 
                          + 3.0 * tei[pqpq] - tei[ppqq]);
231
 
    }
232
 
 
233
 
    /* H_{at,at}, i.e., inactive virt with active orb */
234
 
    else if (p >= lastact && q >= firstact) {
235
 
      a = p;  t = q;
236
 
      aa = ioff[a] + a;
237
 
      tt = ioff[t] + t;
238
 
 
239
 
      hess[pair] = 2.0 * opdm[t][t] * (F_core[aa]);
240
 
 
241
 
      value = 0.0;
242
 
      for (u=firstact; u<lastact; u++) {
243
 
        tu = INDEX(t,u);
244
 
        value += opdm[t][u] * F_core[tu];
245
 
      }
246
 
      hess[pair] -= 2.0 * value;
247
 
 
248
 
      value = 0.0;
249
 
      for (u=firstact; u<lastact; u++) {
250
 
        tu = INDEX(t,u);
251
 
 
252
 
        /* loop over active v,w ... later restrict to symmetry allowed */
253
 
        for (v=firstact; v<lastact; v++) {
254
 
          for (w=firstact; w<lastact; w++) {
255
 
            vw = INDEX(v,w);
256
 
            tuvw = INDEX(tu,vw); 
257
 
            value += tpdm[tuvw] * tei[tuvw];
258
 
          }
259
 
        }
260
 
         
261
 
      }
262
 
      hess[pair] -= 2.0 * value; 
263
 
 
264
 
      value = 0.0;
265
 
      for (u=firstact; u<lastact; u++) {
266
 
        tu = INDEX(t,u);
267
 
        au = INDEX(a,u);
268
 
        for (v=firstact; v<lastact; v++) {
269
 
          uv = INDEX(u,v);
270
 
          av = INDEX(a,v);
271
 
          tv = INDEX(t,v);
272
 
          ttuv = INDEX(tt,uv);
273
 
          aauv = INDEX(aa,uv);
274
 
          tvtu = INDEX(tv,tu);
275
 
          avau = INDEX(av,au);
276
 
          value += ( ( tpdm[ttuv] * tei[aauv] ) + 
277
 
                     ( 2.0 * tpdm[tvtu] * tei[avau] ) );
278
 
        }
279
 
      }
280
 
      hess[pair] += 2.0 * value;
281
 
 
282
 
    } 
283
 
 
284
 
    /* H_{ti,ti}, i.e., active orb with inactive occ */
285
 
    else if (p >= firstact && q < firstact) {
286
 
      t = p;  i = q;
287
 
      tt = ioff[t] + t;
288
 
      ii = ioff[i] + i; 
289
 
      ti = ioff[t] + i;
290
 
      
291
 
      hess[pair] = 2.0 * opdm[t][t] * (F_core[ii]);
292
 
      hess[pair] += 4.0 * (F_core[tt] + F_act[tt] - F_core[ii] - F_act[ii]);
293
 
 
294
 
      value = 0.0;
295
 
      for (u=firstact; u<lastact; u++) {
296
 
        tu = INDEX(t,u);
297
 
        value += opdm[t][u] * F_core[tu];
298
 
      }
299
 
      hess[pair] -= 2.0 * value;
300
 
 
301
 
      value = 0.0;
302
 
      for (u=firstact; u<lastact; u++) {
303
 
        tu = INDEX(t,u);
304
 
 
305
 
        /* loop over active v,w ... later restrict to symmetry allowed */
306
 
        for (v=firstact; v<lastact; v++) {
307
 
          for (w=firstact; w<lastact; w++) {
308
 
            vw = INDEX(v,w);
309
 
            tuvw = INDEX(tu,vw); 
310
 
            value += tpdm[tuvw] * tei[tuvw];
311
 
          }
312
 
        }
313
 
         
314
 
      }
315
 
      hess[pair] -= 2.0 * value; 
316
 
 
317
 
      value = 0.0;
318
 
      for (u=firstact; u<lastact; u++) {
319
 
        tu = INDEX(t,u);
320
 
        ui = INDEX(u,i);
321
 
        for (v=firstact; v<lastact; v++) {
322
 
          uv = INDEX(u,v);
323
 
          tv = INDEX(t,v);
324
 
          vi = INDEX(v,i);
325
 
          ttuv = INDEX(tt,uv);
326
 
          uvii = INDEX(uv,ii);
327
 
          tvtu = INDEX(tv,tu);
328
 
          uivi = INDEX(ui,vi);
329
 
          value += ( ( tpdm[ttuv] * tei[uvii] ) + 
330
 
                     ( 2.0 * tpdm[tvtu] * tei[uivi] ) );
331
 
        }
332
 
      }
333
 
      hess[pair] += 2.0 * value;
334
 
 
335
 
      value = 0.0;
336
 
      for (u=firstact; u<lastact; u++) {
337
 
        tu = INDEX(t,u);
338
 
        ui = INDEX(u,i);
339
 
        uiti = INDEX(ui,ti);
340
 
        tuii = INDEX(tu,ii);
341
 
          /* Create delta(t,u) */
342
 
          delta = 0.0;
343
 
          if( t == u )
344
 
            delta = 1.0;
345
 
          else
346
 
            delta = 0.0;
347
 
        value += ( ( delta - opdm[t][u] ) *
348
 
                   ( ( 3.0 * tei[uiti] ) - tei[tuii] ) );
349
 
      }
350
 
      hess[pair] += 4.0 * value;
351
 
    }
352
 
 
353
 
    /* 
354
 
       H_{t1t2,t1t2}, i.e., active-active (happens for MCSCF, not CASSCF)
355
 
       expression given by personal communication from Galina Chaban,
356
 
       derived from H. J. Aa. Jensen, H. Agren, Chem. Phys. 104, 229 (1982),
357
 
       appendix A.
358
 
    */
359
 
    else if (p >= firstact && q < lastact) {
360
 
      hess[pair] = 2.0 * (  opdm[q][q] * F_core[pp]   
361
 
                          + opdm[p][p] * F_core[qq]
362
 
                          - 2.0 * opdm[p][q] * F_core[pq] );
363
 
      value = 0.0;
364
 
      for (u=firstact; u<lastact; u++) {
365
 
        pu = INDEX(p,u);
366
 
        qu = INDEX(q,u);
367
 
        value += opdm[p][u] * F_core[pu] + opdm[q][u] * F_core[qu];
368
 
        /* should be able to reduce work below by factor of 2 */
369
 
        for (w=firstact; w<lastact; w++) {
370
 
          for (v=firstact; v<lastact; v++) {
371
 
          vw = INDEX(v,w);
372
 
          puvw = INDEX(pu,vw);
373
 
          quvw = INDEX(qu,vw);
374
 
          value += tpdm[puvw] * tei[puvw];
375
 
          value += tpdm[quvw] * tei[quvw]; 
376
 
          }
377
 
        }
378
 
      } 
379
 
      hess[pair] -= value * 2.0;
380
 
 
381
 
      value = 0.0;
382
 
      for (u=firstact; u<lastact; u++) {
383
 
        pu = INDEX(p,u);
384
 
        qu = INDEX(q,u);
385
 
        for (v=firstact; v<lastact; v++) {
386
 
          pv = INDEX(p,v);
387
 
          qv = INDEX(q,v);
388
 
          uv = INDEX(u,v);
389
 
          pupv = INDEX(pu,pv);
390
 
          quqv = INDEX(qu,qv);
391
 
          value += 2.0 * tpdm[pupv] * tei[quqv];
392
 
          value += 2.0 * tpdm[quqv] * tei[pupv]; 
393
 
          ppuv = INDEX(pp,uv);
394
 
          qquv = INDEX(qq,uv);
395
 
          value += tpdm[ppuv] * tei[qquv] + tpdm[qquv] * tei[ppuv];
396
 
          pvqu = INDEX(pv,qu);
397
 
          puqv = INDEX(pu,qv);
398
 
          value -= 4.0 * tpdm[pvqu] * tei[puqv];
399
 
          pquv = INDEX(pq,uv);
400
 
          value -= 2.0 * tpdm[pquv] * tei[pquv];
401
 
        }
402
 
      }
403
 
      hess[pair] += 2.0 * value;
404
 
      if (Params.scale_act_act != 1.0) hess[pair] *= Params.scale_act_act;
405
 
    } /* end case H_{t1t2,t1t2} */
406
 
 
407
 
    else {
408
 
      fprintf(outfile, 
409
 
             "(form_diag_mo_hess): Error, unrecognized class of indep pair\n");
410
 
    }
411
 
 
412
 
  } /* end loop over pairs */
413
 
 
414
 
}
415
 
 
416
 
/*
417
 
** form_full_mo_hess
418
 
**
419
 
** Calculates the full MO Hessian d^2E / (Theta_{pq} Theta_{rs})
420
 
** for independent pairs (p,q) and (r,s).  Assume independent pairs
421
 
** are coming in such that p>=q.
422
 
**
423
 
** d^2 E / (Theta_{pq} Theta_{rs}) = 
424
 
**   y_{pqrs} - y_{qprs} - y_{pqsr} + y_{qpsr}
425
 
**   + 1/2 delta_{ps} ( x_{qr} + x_{rq} )
426
 
**   - 1/2 delta_{qs} ( x_{pr} + x_{rp} )
427
 
**   - 1/2 delta_{pr} ( x_{qs} + x_{sq} )
428
 
**   + 1/2 delta_{qr} ( x_{ps} + x_{sp} )
429
 
**
430
 
** x is the Lagrangian
431
 
** y_{pqrs} = gamma_{qs} 
432
 
**          + \sum_{mn} ( 2 Gamma_{qsmn} (pr|mn) + 4 Gamma_{qmsn} (pm|rn) )
433
 
**
434
 
** note: indices q and s must be populated for y to be nonzero
435
 
**
436
 
** Based on notes by Yukio Yamaguchi (MCSCF eq. 22)
437
 
** We need twice his value to be consistent with the "actual" gradient
438
 
** (his eq. 21, not his eq. 27) or to match G. Chaban, M. W. Schmidt,
439
 
** and M. S. Gordon, Theor. Chem. Acc. 97, 88 (1997).
440
 
**
441
 
** C. David Sherrill
442
 
** September 2003
443
 
*/
444
 
void form_full_mo_hess(int npairs, int *ppair, int *qpair, double *oei,
445
 
  double *tei, double **opdm, double *tpdm, double **lag,
446
 
  double **hess)
447
 
{
448
 
  int npop, nmo;
449
 
  int pair1, pair2, p, q, r, s, m, n;
450
 
  int qs, ps, pr, qr, mn, qm, sn, pm, rn;
451
 
  int qsmn, prmn, qmsn, pmrn, psmn, pmsn, qrmn, qmrn;  
452
 
  double sum, ysum;
453
 
 
454
 
  fprintf(outfile, "Forming full MCSCF orbital Hessian\n");
455
 
 
456
 
  nmo = CalcInfo.nmo;
457
 
  npop = CalcInfo.npop;
458
 
 
459
 
  /* loop over the pairs of independent pairs */
460
 
  for (pair1=0; pair1<npairs; pair1++) {
461
 
    p = ppair[pair1];
462
 
    q = qpair[pair1];
463
 
 
464
 
    for (pair2=0; pair2<=pair1; pair2++) {
465
 
      r = ppair[pair2];
466
 
      s = qpair[pair2];
467
 
 
468
 
      /* compute the hessian contribution for p,q,r,s */
469
 
      sum = 0.0;
470
 
      if (p == s) sum += 0.5 * (lag[q][r] + lag[r][q]);
471
 
      if (q == s) sum -= 0.5 * (lag[p][r] + lag[r][p]);
472
 
      if (p == r) sum -= 0.5 * (lag[q][s] + lag[s][q]);
473
 
      if (q == r) sum += 0.5 * (lag[p][s] + lag[s][p]);
474
 
 
475
 
      pr = INDEX(p,r);
476
 
      qs = INDEX(q,s);
477
 
      ps = INDEX(p,s);
478
 
      qr = INDEX(q,r);
479
 
 
480
 
      /* compute y_{pqrs} */
481
 
      ysum = 0.0;
482
 
      if (q < npop && s < npop) {
483
 
        ysum += oei[pr] * opdm[q][s];
484
 
        for (m=0; m<npop; m++) {
485
 
          qm = INDEX(q,m);
486
 
          pm = INDEX(p,m);
487
 
          for (n=0; n<npop; n++) {
488
 
            mn = INDEX(m,n);
489
 
            sn = INDEX(s,n);
490
 
            rn = INDEX(r,n);
491
 
            qsmn = INDEX(qs,mn);
492
 
            qmsn = INDEX(qm,sn);
493
 
            prmn = INDEX(pr,mn);
494
 
            pmrn = INDEX(pm,rn); 
495
 
            ysum += tpdm[qsmn] * tei[prmn];
496
 
            ysum += 2.0 * tpdm[qmsn] * tei[pmrn];
497
 
          }
498
 
        }
499
 
      }
500
 
      sum += ysum;
501
 
 
502
 
      /* compute y_{qprs} */
503
 
      ysum = 0.0;
504
 
      if (p < npop && s < npop) {
505
 
        ysum += oei[qr] * opdm[p][s];
506
 
        for (m=0; m<npop; m++) {
507
 
          pm = INDEX(p,m);
508
 
          qm = INDEX(q,m);
509
 
          for (n=0; n<npop; n++) {
510
 
            mn = INDEX(m,n);
511
 
            sn = INDEX(s,n);
512
 
            rn = INDEX(r,n);
513
 
            psmn = INDEX(ps,mn);
514
 
            pmsn = INDEX(pm,sn);
515
 
            qrmn = INDEX(qr,mn);
516
 
            qmrn = INDEX(qm,rn); 
517
 
            ysum += tpdm[psmn] * tei[qrmn];
518
 
            ysum += 2.0 * tpdm[pmsn] * tei[qmrn];
519
 
          }
520
 
        }
521
 
      }
522
 
      sum -= ysum;
523
 
 
524
 
      /* compute y_{pqsr} */
525
 
      ysum = 0.0;
526
 
      if (q < npop && r < npop) {
527
 
        ysum += oei[ps] * opdm[q][r];
528
 
        for (m=0; m<npop; m++) {
529
 
          qm = INDEX(q,m);
530
 
          pm = INDEX(p,m);
531
 
          for (n=0; n<npop; n++) {
532
 
            mn = INDEX(m,n);
533
 
            rn = INDEX(r,n);
534
 
            sn = INDEX(s,n);
535
 
            qrmn = INDEX(qr,mn);
536
 
            qmrn = INDEX(qm,rn);
537
 
            psmn = INDEX(ps,mn);
538
 
            pmsn = INDEX(pm,sn); 
539
 
            ysum += tpdm[qrmn] * tei[psmn];
540
 
            ysum += 2.0 * tpdm[qmrn] * tei[pmsn];
541
 
          }
542
 
        }
543
 
      }
544
 
      sum -= ysum;
545
 
 
546
 
      /* compute y_{qpsr} */
547
 
      ysum = 0.0;
548
 
      if (p < npop && r < npop) {
549
 
        ysum += oei[qs] * opdm[p][r];
550
 
        for (m=0; m<npop; m++) {
551
 
          pm = INDEX(p,m);
552
 
          qm = INDEX(q,m);
553
 
          for (n=0; n<npop; n++) {
554
 
            mn = INDEX(m,n);
555
 
            rn = INDEX(r,n);
556
 
            sn = INDEX(s,n);
557
 
            prmn = INDEX(pr,mn);
558
 
            pmrn = INDEX(pm,rn);
559
 
            qsmn = INDEX(qs,mn);
560
 
            qmsn = INDEX(qm,sn); 
561
 
            ysum += tpdm[prmn] * tei[qsmn];
562
 
            ysum += 2.0 * tpdm[pmrn] * tei[qmsn];
563
 
          }
564
 
        }
565
 
      }
566
 
      sum += ysum;
567
 
 
568
 
      hess[pair1][pair2] = 2.0 * sum;
569
 
      hess[pair2][pair1] = 2.0 * sum;
570
 
    } /* end loop over pair2 */
571
 
  } /* end loop over pair1 */
572
 
 
573
 
}
574
 
 
575
 
/*
576
 
** form_diag_mo_hess_yy
577
 
**
578
 
** Calculates the diagonal MO Hessian d^2E / Theta_{pq}^2
579
 
** for independent pair (p,q).  Assume independent pairs
580
 
** are coming in such that p>=q.
581
 
**
582
 
** d^2 E / Theta_{pq}^2
583
 
**   y_{pqpq} - y_{qppq} - y_{pqqp} + y_{qpqp}
584
 
**   - 1/2 delta_{qq} ( x_{pp} + x_{pp} )
585
 
**   - 1/2 delta_{pp} ( x_{qq} + x_{qq} )
586
 
**
587
 
** x is the Lagrangian
588
 
** y_{pqrs} = gamma_{qs} 
589
 
**          + \sum_{mn} ( 2 Gamma_{qsmn} (pr|mn) + 4 Gamma_{qmsn} (pm|rn) )
590
 
**
591
 
** note: indices q and p must be populated for y to be nonzero
592
 
**
593
 
** Based on notes by Yukio Yamaguchi (MCSCF eq. 22)
594
 
**
595
 
** C. David Sherrill
596
 
** September 2003
597
 
*/
598
 
void form_diag_mo_hess_yy(int npairs, int *ppair, int *qpair, double *oei,
599
 
  double *tei, double **opdm, double *tpdm, double **lag,
600
 
  double *hess)
601
 
{
602
 
  int npop, nmo;
603
 
  int pair1, pair2, p, q, m, n;
604
 
  int pq, pp, qq, mn, pn, qn, pm, qm;
605
 
  int qqmn, ppmn, qmqn, pmpn, pqmn, qpmn, pmqn, qmpn;
606
 
  double sum, ysum;
607
 
 
608
 
  fprintf(outfile, "Forming diagonal MCSCF orbital Hessian (YY)\n");
609
 
 
610
 
  nmo = CalcInfo.nmo;
611
 
  npop = CalcInfo.npop;
612
 
 
613
 
  /* loop over the pairs of independent pairs */
614
 
  for (pair1=0; pair1<npairs; pair1++) {
615
 
    p = ppair[pair1];
616
 
    q = qpair[pair1];
617
 
 
618
 
    pq = INDEX(p,q);
619
 
    pp = ioff[p] + p;
620
 
    qq = ioff[q] + q;
621
 
 
622
 
    /* compute the hessian contribution for p,q,p,q */
623
 
    sum = - lag[p][p] - lag[q][q];
624
 
 
625
 
    /* compute y_{pqpq} */
626
 
    ysum = 0.0;
627
 
    if (q < npop) {
628
 
      ysum += oei[pp] * opdm[q][q];
629
 
       
630
 
      for (m=0; m<npop; m++) {
631
 
        pm = INDEX(p,m);
632
 
        qm = INDEX(q,m);
633
 
        for (n=0; n<npop; n++) {
634
 
          mn = INDEX(m,n);
635
 
          pn = INDEX(p,n);
636
 
          qn = INDEX(q,n);
637
 
          qqmn = INDEX(qq,mn);
638
 
          ppmn = INDEX(pp,mn);
639
 
          qmqn = INDEX(qm,qn);
640
 
          pmpn = INDEX(pm,pn);
641
 
          ysum += tpdm[qqmn] * tei[ppmn];
642
 
          ysum += 2.0 * tpdm[qmqn] * tei[pmpn];
643
 
        }
644
 
      }
645
 
    }
646
 
    sum += ysum;
647
 
 
648
 
    /* compute y_{qppq} = y_{pqqp} */
649
 
    ysum = 0.0;
650
 
    if (p < npop && q < npop) {
651
 
      ysum += oei[pq] * opdm[p][q];
652
 
      for (m=0; m<npop; m++) {
653
 
        pm = INDEX(p,m);
654
 
        qm = INDEX(q,m);
655
 
        for (n=0; n<npop; n++) {
656
 
          mn = INDEX(m,n);
657
 
          qn = INDEX(q,n);
658
 
          pn = INDEX(p,n);
659
 
          pqmn = INDEX(pq,mn);
660
 
          pmqn = INDEX(pm,qn);
661
 
          qmpn = INDEX(qm,pn); 
662
 
 
663
 
          ysum += tpdm[pqmn] * tei[pqmn];
664
 
          ysum += 2.0 * tpdm[pmqn] * tei[qmpn];
665
 
        }
666
 
      }
667
 
    }
668
 
    sum -= 2.0 * ysum;
669
 
 
670
 
    /* compute y_{qpqp} */
671
 
    ysum = 0.0;
672
 
    if (p < npop) {
673
 
      ysum += oei[qq] * opdm[p][p];
674
 
      for (m=0; m<npop; m++) {
675
 
        pm = INDEX(p,m);
676
 
        qm = INDEX(q,m);
677
 
        for (n=0; n<npop; n++) {
678
 
          mn = INDEX(m,n);
679
 
          pn = INDEX(p,n);
680
 
          qn = INDEX(q,n);
681
 
          ppmn = INDEX(pp,mn);
682
 
          qqmn = INDEX(qq,mn);
683
 
          pmpn = INDEX(pm,pn);
684
 
          qmqn = INDEX(qm,qn);
685
 
 
686
 
          ysum += tpdm[ppmn] * tei[qqmn];
687
 
          ysum += 2.0 * tpdm[pmpn] * tei[qmqn];
688
 
        }
689
 
      }
690
 
    }
691
 
    sum += ysum;
692
 
 
693
 
    hess[pair1] = 2.0 * sum;
694
 
  } /* end loop over pair1 */
695
 
 
696
 
}
697