3
\brief Enter brief description of file here
8
** Routines for Direct Inversion of the Iterative Subspace Interpolation
9
** of orbital rotation angles, P. Pulay, Chem. Phys. Lett. 73, 393 (1980).
12
** University of California, Berkeley
19
#include <libciomr/libciomr.h>
20
#include "globaldefs.h"
23
namespace psi { namespace detcas {
25
#define DIIS_MIN_DET 1.0E-16
30
** This top-level routine manages all the DIIS stuff.
33
** veclen = length of the vectors to extrapolate
34
** vec = new vector to add
35
** errvec = new error vector to add
38
** 1 if DIIS step taken, otherwise 0
40
int diis(int veclen, double *vec, double *errvec)
43
int num_vecs, new_num_vecs, offset, diis_iter, do_diis;
44
double **vecs, **errvecs, **bmat, *bvec, tval, det, scale_factor;
48
/* add the vector and error vector to subspace */
49
ffileb_noexit(&fp,"diis.dat",2);
52
if (fread(&num_vecs, sizeof(int), 1, fp) != 1) {
53
fprintf(outfile, "(diis): Error reading number of diis vectors.\n");
57
if (fread(&diis_iter, sizeof(int), 1, fp) != 1) {
58
fprintf(outfile, "(diis): Error reading diis iteration number.\n");
62
vecs = block_matrix(num_vecs+1, veclen);
63
errvecs = block_matrix(num_vecs+1, veclen);
65
for (i=0; i<num_vecs; i++) {
67
if (fread(vecs[i], sizeof(double), veclen, fp) != veclen) {
68
fprintf(outfile, "(diis): Error reading diis vector %d\n", i);
72
if (fread(errvecs[i], sizeof(double), veclen, fp) != veclen) {
73
fprintf(outfile, "(diis): Error reading diis error vector %d\n", i);
85
vecs = block_matrix(num_vecs+1, veclen);
86
errvecs = block_matrix(num_vecs+1, veclen);
89
/* will we do a diis this time? */
92
if ((diis_iter % Params.diis_freq) || (num_vecs < Params.diis_min_vecs))
97
for (i=0; i<veclen; i++) vecs[num_vecs-1][i] = vec[i];
98
for (i=0; i<veclen; i++) errvecs[num_vecs-1][i] = errvec[i];
101
if (num_vecs > Params.diis_max_vecs)
102
offset = num_vecs - Params.diis_max_vecs;
104
if (Params.print_lvl > 2)
105
fprintf(outfile, "Diis: iter %2d, vecs %d, do_diis %d, offset %d\n",
106
diis_iter, num_vecs, do_diis, offset);
108
new_num_vecs = num_vecs - offset;
110
/* write out the diis info */
111
ffileb_noexit(&fp,"diis.dat",0);
113
fprintf(outfile, "(diis): Error opening diis.dat\n");
117
if (fwrite(&new_num_vecs, sizeof(int), 1, fp) != 1) {
118
fprintf(outfile, "(diis): Error writing number of diis vectors.\n");
122
if (fwrite(&diis_iter, sizeof(int), 1, fp) != 1) {
123
fprintf(outfile, "(diis): Error writing diis iteration number.\n");
127
for (i=offset; i<num_vecs; i++) {
128
if (fwrite(vecs[i], sizeof(double), veclen, fp) != veclen) {
129
fprintf(outfile, "(diis): Error writing vector %d.\n", i);
131
if (fwrite(errvecs[i], sizeof(double), veclen, fp) != veclen) {
132
fprintf(outfile, "(diis): Error writing error vector %d.\n", i);
139
/* don't take a diis step if it's not time */
146
/* form diis matrix, solve equations */
147
if (Params.print_lvl)
148
fprintf(outfile, "Attempting a DIIS step\n");
150
bmat = block_matrix(new_num_vecs+1, new_num_vecs+1);
151
bvec = init_array(new_num_vecs+1);
153
for (i=0; i<new_num_vecs; i++) {
154
for (j=0; j<=i; j++) {
156
for (k=0; k<veclen; k++) {
157
tval += errvecs[i+offset][k] * errvecs[j+offset][k];
164
for (i=0; i<new_num_vecs; i++) {
165
bmat[i][new_num_vecs] = -1.0;
166
bmat[new_num_vecs][i] = -1.0;
169
bmat[new_num_vecs][new_num_vecs] = 0.0;
170
bvec[new_num_vecs] = -1.0;
172
if (Params.print_lvl > 2) {
173
fprintf(outfile, "DIIS B Matrix:\n");
174
print_mat(bmat, new_num_vecs+1, new_num_vecs+1, outfile);
177
/* scale the B matrix */
178
scale_factor = 1.0 / bmat[0][0];
179
for (i=0; i<new_num_vecs; i++) {
180
for (j=0; j<new_num_vecs; j++) {
181
bmat[i][j] = bmat[i][j] * scale_factor;
185
if (Params.print_lvl > 2) {
186
fprintf(outfile, "DIIS B Matrix:\n");
187
print_mat(bmat, new_num_vecs+1, new_num_vecs+1, outfile);
190
/* now solve the linear equations */
191
flin(bmat, bvec, new_num_vecs+1, 1, &det);
193
if (fabs(det) < DIIS_MIN_DET) {
194
fprintf(outfile, "Warning: diis matrix near-singular\n");
195
fprintf(outfile, "Determinant is %6.3E\n", det);
198
if (Params.print_lvl > 3) {
199
fprintf(outfile, "\nCoefficients of DIIS extrapolant:\n");
200
for (i=0; i<new_num_vecs; i++) {
201
fprintf(outfile, "%12.6lf\n", bvec[i]);
203
fprintf(outfile, "Lambda:\n");
204
fprintf(outfile, "%12.6lf\n", bvec[i]);
207
/* get extrapolated vector */
208
zero_arr(CalcInfo.theta_cur, veclen);
209
for (i=0; i<new_num_vecs; i++) {
210
for (j=0; j<veclen; j++) {
211
CalcInfo.theta_cur[j] += bvec[i] * vecs[i+offset][j];
223
}} // end namespace psi::detcas