2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
43 #include "types/simple.h"
45 #include "gmx_fatal.h"
47 #include "sparsematrix.h"
48 #include "eigensolver.h"
51 #define F77_FUNC(name,NAME) name ## _
54 #include "gmx_lapack.h"
55 #include "gmx_arpack.h"
80 /* Make jobz point to the character "V" if eigenvectors
81 * should be calculated, otherwise "N" (only eigenvalues).
83 jobz = (eigenvectors != NULL) ? "V" : "N";
85 /* allocate lapack stuff */
89 /* First time we ask the routine how much workspace it needs */
94 /* Convert indices to fortran standard */
98 /* Call LAPACK routine using fortran interface. Note that we use upper storage,
99 * but this corresponds to lower storage ("L") in Fortran.
102 F77_FUNC(dsyevr,DSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
103 &abstol,&m,eigenvalues,eigenvectors,&n,
104 isuppz,&w0,&lwork,&iw0,&liwork,&info);
106 F77_FUNC(ssyevr,SSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
107 &abstol,&m,eigenvalues,eigenvectors,&n,
108 isuppz,&w0,&lwork,&iw0,&liwork,&info);
114 gmx_fatal(FARGS,"Internal errror in LAPACK diagonalization.");
126 F77_FUNC(dsyevr,DSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
127 &abstol,&m,eigenvalues,eigenvectors,&n,
128 isuppz,work,&lwork,iwork,&liwork,&info);
130 F77_FUNC(ssyevr,SSYEVR)(jobz,"I","L",&n,a,&n,&vl,&vu,&index_lower,&index_upper,
131 &abstol,&m,eigenvalues,eigenvectors,&n,
132 isuppz,work,&lwork,iwork,&liwork,&info);
141 gmx_fatal(FARGS,"Internal errror in LAPACK diagonalization.");
149 sparse_parallel_eigensolver(gmx_sparsematrix_t * A,
163 int ido,info,lworkl,i,ncv,dovec;
169 MPI_Comm_size( MPI_COMM_WORLD, &nnodes );
170 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
172 if(eigenvectors != NULL)
184 iparam[i]=ipntr[i]=0;
186 iparam[0] = 1; /* Don't use explicit shifts */
187 iparam[2] = maxiter; /* Max number of iterations */
188 iparam[6] = 1; /* Standard symmetric eigenproblem */
190 lworkl = ncv*(8+ncv);
197 /* Use machine tolerance - roughly 1e-16 in double precision */
201 fprintf(stderr,"Calculation Ritz values and Lanczos vectors, max %d iterations...\n",maxiter);
206 F77_FUNC(pdsaupd,PDSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
207 resid, &ncv, v, &n, iparam, ipntr,
208 workd, iwork, workl, &lworkl, &info);
210 F77_FUNC(pssaupd,PSSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
211 resid, &ncv, v, &n, iparam, ipntr,
212 workd, iwork, workl, &lworkl, &info);
214 if(ido==-1 || ido==1)
215 gmx_sparsematrix_vector_multiply(A,workd+ipntr[0]-1, workd+ipntr[1]-1);
217 fprintf(stderr,"\rIteration %4d: %3d out of %3d Ritz values converged.",iter++,iparam[4],neig);
218 } while(info==0 && (ido==-1 || ido==1));
220 fprintf(stderr,"\n");
224 "Maximum number of iterations (%d) reached in Arnoldi\n"
225 "diagonalization, but only %d of %d eigenvectors converged.\n",
226 maxiter,iparam[4],neig);
230 gmx_fatal(FARGS,"Unspecified error from Arnoldi diagonalization:%d\n",info);
234 /* Extract eigenvalues and vectors from data */
235 fprintf(stderr,"Calculating eigenvalues and eigenvectors...\n");
238 F77_FUNC(pdseupd,PDSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
239 &n, NULL, "I", &n, "SA", &neig, &abstol,
240 resid, &ncv, v, &n, iparam, ipntr,
241 workd, workl, &lworkl, &info);
243 F77_FUNC(psseupd,PSSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
244 &n, NULL, "I", &n, "SA", &neig, &abstol,
245 resid, &ncv, v, &n, iparam, ipntr,
246 workd, workl, &lworkl, &info);
259 sparse_eigensolver(gmx_sparsematrix_t * A,
273 int ido,info,lworkl,i,ncv,dovec;
279 MPI_Comm_size( MPI_COMM_WORLD, &n );
282 sparse_parallel_eigensolver(A,neig,eigenvalues,eigenvectors,maxiter);
287 if(eigenvectors != NULL)
299 iparam[i]=ipntr[i]=0;
301 iparam[0] = 1; /* Don't use explicit shifts */
302 iparam[2] = maxiter; /* Max number of iterations */
303 iparam[6] = 1; /* Standard symmetric eigenproblem */
305 lworkl = ncv*(8+ncv);
312 /* Use machine tolerance - roughly 1e-16 in double precision */
316 fprintf(stderr,"Calculation Ritz values and Lanczos vectors, max %d iterations...\n",maxiter);
321 F77_FUNC(dsaupd,DSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
322 resid, &ncv, v, &n, iparam, ipntr,
323 workd, iwork, workl, &lworkl, &info);
325 F77_FUNC(ssaupd,SSAUPD)(&ido, "I", &n, "SA", &neig, &abstol,
326 resid, &ncv, v, &n, iparam, ipntr,
327 workd, iwork, workl, &lworkl, &info);
329 if(ido==-1 || ido==1)
330 gmx_sparsematrix_vector_multiply(A,workd+ipntr[0]-1, workd+ipntr[1]-1);
332 fprintf(stderr,"\rIteration %4d: %3d out of %3d Ritz values converged.",iter++,iparam[4],neig);
333 } while(info==0 && (ido==-1 || ido==1));
335 fprintf(stderr,"\n");
339 "Maximum number of iterations (%d) reached in Arnoldi\n"
340 "diagonalization, but only %d of %d eigenvectors converged.\n",
341 maxiter,iparam[4],neig);
345 gmx_fatal(FARGS,"Unspecified error from Arnoldi diagonalization:%d\n",info);
349 /* Extract eigenvalues and vectors from data */
350 fprintf(stderr,"Calculating eigenvalues and eigenvectors...\n");
353 F77_FUNC(dseupd,DSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
354 &n, NULL, "I", &n, "SA", &neig, &abstol,
355 resid, &ncv, v, &n, iparam, ipntr,
356 workd, workl, &lworkl, &info);
358 F77_FUNC(sseupd,SSEUPD)(&dovec, "A", select, eigenvalues, eigenvectors,
359 &n, NULL, "I", &n, "SA", &neig, &abstol,
360 resid, &ncv, v, &n, iparam, ipntr,
361 workd, workl, &lworkl, &info);