3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #include "eigensolver.h"
37 #include "gromacs/legacyheaders/types/simple.h"
38 #include "gromacs/legacyheaders/gmx_fatal.h"
39 #include "gromacs/legacyheaders/smalloc.h"
41 #include "gromacs/linearalgebra/sparsematrix.h"
42 #include "gmx_lapack.h"
43 #include "gmx_arpack.h"
68 /* Make jobz point to the character "V" if eigenvectors
69 * should be calculated, otherwise "N" (only eigenvalues).
71 jobz = (eigenvectors != NULL) ? "V" : "N";
73 /* allocate lapack stuff */
77 /* First time we ask the routine how much workspace it needs */
82 /* Convert indices to fortran standard */
86 /* Call LAPACK routine using fortran interface. Note that we use upper storage,
87 * but this corresponds to lower storage ("L") in Fortran.
90 F77_FUNC(dsyevr,DSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
91 &abstol,&m,eigenvalues,eigenvectors,&n,
92 isuppz,&w0,&lwork,&iw0,&liwork,&info);
94 F77_FUNC(ssyevr,SSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
95 &abstol,&m,eigenvalues,eigenvectors,&n,
96 isuppz,&w0,&lwork,&iw0,&liwork,&info);
102 gmx_fatal(FARGS,"Internal errror in LAPACK diagonalization.");
114 F77_FUNC(dsyevr,DSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
115 &abstol,&m,eigenvalues,eigenvectors,&n,
116 isuppz,work,&lwork,iwork,&liwork,&info);
118 F77_FUNC(ssyevr,SSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
119 &abstol,&m,eigenvalues,eigenvectors,&n,
120 isuppz,work,&lwork,iwork,&liwork,&info);
129 gmx_fatal(FARGS,"Internal errror in LAPACK diagonalization.");
137 sparse_parallel_eigensolver(gmx_sparsematrix_t * A,
151 int ido,info,lworkl,i,ncv,dovec;
157 MPI_Comm_size( MPI_COMM_WORLD, &nnodes );
158 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
160 if(eigenvectors != NULL)
172 iparam[i]=ipntr[i]=0;
174 iparam[0] = 1; /* Don't use explicit shifts */
175 iparam[2] = maxiter; /* Max number of iterations */
176 iparam[6] = 1; /* Standard symmetric eigenproblem */
178 lworkl = ncv*(8+ncv);
185 /* Use machine tolerance - roughly 1e-16 in double precision */
189 fprintf(stderr,"Calculation Ritz values and Lanczos vectors, max %d iterations...\n",maxiter);
194 F77_FUNC(pdsaupd,PDSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
195 resid, &ncv, v, &n, iparam, ipntr,
196 workd, iwork, workl, &lworkl, &info);
198 F77_FUNC(pssaupd,PSSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
199 resid, &ncv, v, &n, iparam, ipntr,
200 workd, iwork, workl, &lworkl, &info);
202 if(ido==-1 || ido==1)
203 gmx_sparsematrix_vector_multiply(A,workd+ipntr[0]-1, workd+ipntr[1]-1);
205 fprintf(stderr,"\rIteration %4d: %3d out of %3d Ritz values converged.",iter++,iparam[4],neig);
206 } while(info==0 && (ido==-1 || ido==1));
208 fprintf(stderr,"\n");
212 "Maximum number of iterations (%d) reached in Arnoldi\n"
213 "diagonalization, but only %d of %d eigenvectors converged.\n",
214 maxiter,iparam[4],neig);
218 gmx_fatal(FARGS,"Unspecified error from Arnoldi diagonalization:%d\n",info);
222 /* Extract eigenvalues and vectors from data */
223 fprintf(stderr,"Calculating eigenvalues and eigenvectors...\n");
226 F77_FUNC(pdseupd,PDSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
227 &n, NULL, "I", &n, "SA", &neig, &abstol,
228 resid, &ncv, v, &n, iparam, ipntr,
229 workd, workl, &lworkl, &info);
231 F77_FUNC(psseupd,PSSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
232 &n, NULL, "I", &n, "SA", &neig, &abstol,
233 resid, &ncv, v, &n, iparam, ipntr,
234 workd, workl, &lworkl, &info);
247 sparse_eigensolver(gmx_sparsematrix_t * A,
261 int ido,info,lworkl,i,ncv,dovec;
267 MPI_Comm_size( MPI_COMM_WORLD, &n );
270 sparse_parallel_eigensolver(A,neig,eigenvalues,eigenvectors,maxiter);
275 if(eigenvectors != NULL)
287 iparam[i]=ipntr[i]=0;
289 iparam[0] = 1; /* Don't use explicit shifts */
290 iparam[2] = maxiter; /* Max number of iterations */
291 iparam[6] = 1; /* Standard symmetric eigenproblem */
293 lworkl = ncv*(8+ncv);
300 /* Use machine tolerance - roughly 1e-16 in double precision */
304 fprintf(stderr,"Calculation Ritz values and Lanczos vectors, max %d iterations...\n",maxiter);
309 F77_FUNC(dsaupd,DSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
310 resid, &ncv, v, &n, iparam, ipntr,
311 workd, iwork, workl, &lworkl, &info);
313 F77_FUNC(ssaupd,SSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
314 resid, &ncv, v, &n, iparam, ipntr,
315 workd, iwork, workl, &lworkl, &info);
317 if(ido==-1 || ido==1)
318 gmx_sparsematrix_vector_multiply(A,workd+ipntr[0]-1, workd+ipntr[1]-1);
320 fprintf(stderr,"\rIteration %4d: %3d out of %3d Ritz values converged.",iter++,iparam[4],neig);
321 } while(info==0 && (ido==-1 || ido==1));
323 fprintf(stderr,"\n");
327 "Maximum number of iterations (%d) reached in Arnoldi\n"
328 "diagonalization, but only %d of %d eigenvectors converged.\n",
329 maxiter,iparam[4],neig);
333 gmx_fatal(FARGS,"Unspecified error from Arnoldi diagonalization:%d\n",info);
337 /* Extract eigenvalues and vectors from data */
338 fprintf(stderr,"Calculating eigenvalues and eigenvectors...\n");
341 F77_FUNC(dseupd,DSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
342 &n, NULL, "I", &n, "SA", &neig, &abstol,
343 resid, &ncv, v, &n, iparam, ipntr,
344 workd, workl, &lworkl, &info);
346 F77_FUNC(sseupd,SSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
347 &n, NULL, "I", &n, "SA", &neig, &abstol,
348 resid, &ncv, v, &n, iparam, ipntr,
349 workd, workl, &lworkl, &info);