pax_global_header00006660000000000000000000000064126066600120014511gustar00rootroot0000000000000052 comment=b0f7a6008f37f913e97f67c826fc37fa9758f626 arpack-ng-3.3.0/000077500000000000000000000000001260666001200133575ustar00rootroot00000000000000arpack-ng-3.3.0/.gitignore000066400000000000000000000014741260666001200153550ustar00rootroot00000000000000.hgignore # Generated by `autoreconf` Makefile.in aclocal.m4 autom4te.cache/ m4/libtool.m4 m4/lt*.m4 configure config.guess config.sub depcomp install-sh ltmain.sh missing # Generated by `./configure` Makefile config.log config.status libtool .deps/ arpack.pc # Generated by `make` *.o *.lo *.la .libs/ # Generated by `make check` TESTS/dnsimp TESTS/bug_1315_double TESTS/bug_1315_single TESTS/bug_1323 EXAMPLES/BAND/[sd][sn]bdr[123456] EXAMPLES/BAND/[cz]nbdr[1234] EXAMPLES/COMPLEX/[cz]ndrv[1234] EXAMPLES/NONSYM/[sd]ndrv[123456] EXAMPLES/SIMPLE/[sd]ssimp EXAMPLES/SIMPLE/[sdcz]nsimp EXAMPLES/SVD/[sd]svd EXAMPLES/SYM/[sd]sdrv[123456] PARPACK/EXAMPLES/MPI/p[sd]ndrv[13] PARPACK/EXAMPLES/MPI/p[sd]sdrv1 PARPACK/EXAMPLES/MPI/p[cz]ndrv1 *.lib *.def *.dll *.bak *.exp *.u2d *.suo VISUAL_STUDIO/Release MKL/ VISUAL_STUDIO/bin/ arpack-ng-3.3.0/.hgignore000066400000000000000000000006731260666001200151700ustar00rootroot00000000000000syntax: glob .gitignore Makefile *.o *.lo *.la .libs/ SRC/.libs/ UTIL/.libs/ arpack.pc autom4te.cache/ config.log config.status libtool *.lib *.def *.dll *.bak *.exp *.u2d *.suo VISUAL_STUDIO/Release MKL/ VISUAL_STUDIO/bin/ TESTS/dnsimp PARPACK/EXAMPLES/MPI/pcndrv1 PARPACK/EXAMPLES/MPI/pdndrv1 PARPACK/EXAMPLES/MPI/pdndrv3 PARPACK/EXAMPLES/MPI/pdsdrv1 PARPACK/EXAMPLES/MPI/psndrv3 PARPACK/EXAMPLES/MPI/pssdrv1 PARPACK/EXAMPLES/MPI/pzndrv1 arpack-ng-3.3.0/.travis.yml000066400000000000000000000004311260666001200154660ustar00rootroot00000000000000sudo: false language: c compiler: - gcc addons: apt: packages: - gfortran - libopenblas-dev - liblapack-dev - libopenmpi-dev - openmpi-bin script: - ./bootstrap - ./configure --enable-mpi - make all - make check - make distcheck arpack-ng-3.3.0/CHANGES000066400000000000000000000141601260666001200143540ustar00rootroot00000000000000arpack-ng - 3.3.0 [ Denis Davydov ] * Rename pdlamch to pdlamch10 to avoid symbol collision with Scalapack 2.0.2 in MPI context. [ Kyle Guinn ] * General improvements on the build system * libparpack links against libarpack (instead of doing a static link) [Guillaume Horel] * reverts using {d,s}lahqr from lapack 2 * use dlahqr from lapack 3 instead of dlaqrb (credit to Marco Caliari) -- Sylvestre Ledru Mon, 12 October 2015 08:40:51 +0200 arpack-ng - 3.2.0 * Switch to github - https://github.com/opencollab/arpack-ng/ * Fix dsneupd select/calculate wrong eigenpairs if rvec = true by using dlahqr and slahqr from lapack2 (Closes: #3) -- Sylvestre Ledru Sat, 14 Nov 2014 16:25:36 +0200 arpack-ng - 3.1.5 * Build all examples and run them as tests * Fix the version of arpack-ng itself * Switch to automake 1.14.1 [ Ruediger Meier ] * Do not install test binaries (Closes: #1348) [ Nikita Styopin ] * Fix the diagonal matrix example (dndrv5) (Closes: #1397) -- Sylvestre Ledru Sat, 15 Feb 2014 14:24:42 +0200 arpack-ng - 3.1.4 * libparpack2: missing dependency on MPI: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718790 * Replace LAPACK second function with ARPACK's own arscnd in PARPACK * Fix issue #1259 in DSEUPD and SSEUPD The Ritz vector purification step assumes workl(iq) still contains the original Q matrix. This is however overwritten by the call to xGEQR2 earlier. . This patch fixes the issue by making a copy of the last row of the eigenvector matrix, after it is recomputed after QR by xORM2R. The work space WORKL(IW+NCV:IW+2*NCV) is not used later in the routine, and can be used for this. * Use configure supplied blas and lapack in the pkg-config. Thanks to Ward Poelmans (Closes: #1320) * Switch to automake 1.14 + libtool 2.4.2. Thanks to Ward Poelmans (Closes: #1321) * dseupd routine may lead to a segmentation fault Thanks to Edouard Canot (Closes: #1323) * dsaupd and 'BE' option returns wrong eigenvalues for a SPD matrix Thanks to Edouard Canot (Closes: #1329) -- Sylvestre Ledru Mon, 07 Oct 2013 14:24:42 +0200 arpack-ng - 3.1.3 [ Jordi Gutiérrez Hermoso ] * Replace depcomp symlink with actual file. * Update libtool usage. Thanks to John W. Eaton . * Replace arpack.pc with proper autotooled arpack.pc.in * Add debug.h to TESTS/Makefile.am sources * "make dist" is functionnal * Also build the library "libparpacksrcblacs" (PARPACK/UTIL/BLACS/) -- Sylvestre Ledru Tue, 02 Apr 2013 10:53:08 +0200 arpack-ng - 3.1.2 * Wrong call to pdlamch was causing segfaults Thanks to Kyrre Sjøbæk for finding the bug and the fix. * Get rid of the mpif.h occurences in the source code (Closes: #782) * Compile also PARPACK / MPI example (Closes: #783) * Configure detected built-in LAPACK and BLAS, but refused to use them (Closes: #784) * Fixed division by zero in smlnum by usind p[d,s]lamch instead of the serial. Thanks to Umberto De Giovannini. -- Sylvestre Ledru Fri, 22 Jun 2012 22:05:41 +0200 arpack-ng - 3.1.1 * Option --enable-maintainer-mode added to the configure * --disable-mpi disables the build of parpack (Closes: #714) * Switch to automake 1.11.3 -- Sylvestre Ledru Mon, 21 May 2012 09:08:41 +0200 arpack-ng - 3.1.0 * Many bug fixes in the parpack lib. It is an old patch from upstream. Thanks to Viral Shah for pinging us on this subject. See the PARPACK_CHANGES file for the details. * Change the bug report from arpack@caam.rice.edu to http://forge.scilab.org/index.php/p/arpack-ng/issues/ * Provide a M4 macro (detect_arpack_bug.m4) to check if the underlying arpack is buggy (ie not arpack-ng). This allows developper applications to perform the check in their autotools build system (configure). * Fixed a lack of appropriate bounds check in DNAUP2. Thanks to Pauli Virtanen for the patch (Closes: #632) * Update of the doc about TOL in dnaupd. * Reorder bug fixed when eigenvectors are requested and the resulting number of converged eigenvalues is less than the number requested. Patches from Tim Mitchell. (Closes: #664) * TESTS/ directory added and built. -- Sylvestre Ledru Wed, 22 Feb 2012 10:58:39 +0100 arpack-ng - 3.0.2 * Fix a long line in pznaup2.f which was showing some wrong symbols (Closes: #620) * README content updated regarding ARPACK-NG * arpack.pc (pkg-config) file added * Update the title & version in the configure.ac * Always search for MPILIBS (in order to have the variable correctly set) * Explicitly link against MPI fortran libs for parpack -- Sylvestre Ledru Wed, 28 Dec 2011 13:45:53 +0100 arpack-ng - 3.0.1 * libtool was missing (Closes: #615) * Missing license information (Closes: #614) * TODO added -- Sylvestre Ledru Tue, 13 Dec 2011 16:33:25 +0100 arpack-ng - 3.0 * Patches from Scilab second_NONE used by default (TO DO replace by second in LAPACK) second_NONE works with all fortrans compilers (used by default with Scilab) sneupd.f, cneupd.f: modified for scilab add a check on nconv value (Scilab bug fix) dnaupd.f: modified NEV Integer: INPUT/OUTPUT before only INPUT (Scilab bug fix) * Patches from Octave: (Thanks to John W. EATON) dneupd.f: Restore value of nconv dseupd.f: Restore value of nconv sseupd.f: Change GOTO target to eliminate warning about landing on end if. zneupd.f: Restore value of nconv * Compilation Apply gentoo patches to use an autotools build system Build system updated to build with Visual Studio 2010 + Intel fortran 2011 compiles on Windows. Specify the SONAME to libarpack.so.2 (no API/ABI changes compare to version 2.0) -- Sylvestre Ledru Sat, 10 Dec 2011 20:32:45 +0100 arpack-ng-3.3.0/COPYING000066400000000000000000000035441260666001200144200ustar00rootroot00000000000000 BSD Software License Pertains to ARPACK and P_ARPACK Copyright (c) 1996-2008 Rice University. Developed by D.C. Sorensen, R.B. Lehoucq, C. Yang, and K. Maschhoff. All rights reserved. Arpack has been renamed to arpack-ng. Copyright (c) 2001-2011 - Scilab Enterprises Updated by Allan Cornet, Sylvestre Ledru. Copyright (c) 2010 - Jordi Gutiérrez Hermoso (Octave patch) Copyright (c) 2007 - Sébastien Fabbro (gentoo patch) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer listed in this license in the documentation and/or other materials provided with the distribution. - Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. arpack-ng-3.3.0/DOCUMENTS/000077500000000000000000000000001260666001200147205ustar00rootroot00000000000000arpack-ng-3.3.0/DOCUMENTS/README000066400000000000000000000010671260666001200156040ustar00rootroot00000000000000 There are five documents within the DOCUMENT subdirectory. In summary, ex-nonsym.doc, ex-sym.doc and ex-complex.doc ------------- ---------- -------------- Example Templates of how to invoke the different computational modes offered by [D,S]NAUPD, [D,S]SAUPD and [C,Z]NAUPD. stat.doc -------- File that gets timing statistics for the different parts of the Arnoldi update iteration codes within ARPACK. debug.doc --------- File that explains the different printing options of the Arnoldi update iteration codes within ARPACK. arpack-ng-3.3.0/DOCUMENTS/debug.doc000066400000000000000000000410351260666001200165000ustar00rootroot00000000000000 ARPACK provides a means to trace the progress of the computation as it proceeds. Various levels of output may be specified from no output, level = 0, to voluminous, level = 3. The following statements may be used within the calling program to initiate and request this output. include 'debug.h' ndigit = -3 logfil = 6 msgets = 0 msaitr = 0 msapps = 0 msaupd = 1 msaup2 = 0 mseigt = 0 mseupd = 0 The parameter "logfil" specifies the logical unit number of the output file. The parameter "ndigit" specifies the number of decimal digits and the width of the output lines. A positive value of "ndigit" specifies that 132 columns are used during output and a negative value specifies eighty columns are to be used. The values of the remaining parameters indicate the output levels from the indicated routines. For the above example, "msaitr" indicates the level of output requested for the subroutine ssaitr or dsaitr. The above configuration will give a breakdown of the number of matrix vector products required, the total number of iterations, the number of re-orthogonalization steps and an estimate of the time spent in each routine and phase of the computation. The following output is produced: --------------------------------------------------------------------- ========================================== = Symmetric implicit Arnoldi update code = = Version Number: 2.1 = = Version Date: 11/15/95 = ========================================== = Summary of timing statistics = ========================================== Total number update iterations = 8 Total number of OP*x operations = 125 Total number of B*x operations = 0 Total number of reorthogonalization steps = 125 Total number of iterative refinement steps = 0 Total number of restart steps = 0 Total time in user OP*x operation = 0.020002 Total time in user B*x operation = 0.000000 Total time in Arnoldi update routine = 0.210021 Total time in ssaup2 routine = 0.190019 Total time in basic Arnoldi iteration loop = 0.110011 Total time in reorthogonalization phase = 0.070007 Total time in (re)start vector generation = 0.000000 Total time in trid eigenvalue subproblem = 0.040004 Total time in getting the shifts = 0.000000 Total time in applying the shifts = 0.040004 Total time in convergence testing = 0.000000 --------------------------------------------------------------------- The user is encouraged to experiment with the other settings once some familiarity has been gained with the routines. The include statement sets up the storage declarations that are solely associated with this trace debugging feature. "debug.h" has the following structure: --------------------------------------------------------------------- c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd --------------------------------------------------------------------- The parameters "msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd" are for the symmetric codes, while "mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd" are for the nonsymmetric codes and, finally, "mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd" are for the complex arithmetic codes. A comprehensive break down of each parameter is given below. ========================================================== === Common to symmetric, nonsymmetric and complex code === ========================================================== logfil: unit number where the logfile (debug) is written ndigit: number of digits used in the debug output ndigit < 0: printing is done with 72 columns. ndigit > 0: printing is done with 132 columns. mgetv0 > 0: print residual vector generated. ====================================== === Specific to the symmetric code === ====================================== msaupd > 0: *Print the number of iterations taken, number of "converged" eigenvalues, final Ritz values and corresponding Ritz estimates. *Print various timing statistics. msaup2 > 0: *Print major iteration number, number of "converged" Ritz values on exit, B-norm of the residual vector of length NCV factorization, B-norm of the residual vector of length NEV factorization, residual norm before exit, Ritz values and corresponding Ritz estimates before exit. msaup2 > 1: print number of unreduced submatrices, Ritz values and corresponding Ritz estimates of the current T matrix, actual values for NEV and NP, wanted Ritz values and corresponding Ritz estimates, shifts selected. msaup2 > 2: print "unwanted" Ritz values and corresponding Ritz estimates, order NCV matrix T (diagonal and off-diagonal), unwanted Ritz values and error bounds. msaitr > 0: print iteration number, residual norm, restart info print if an off diagonal element of T became negative. msaitr > 1: print the final matrix T. msaitr > 2: print Arnoldi vector no. generate at iteration j, b-norm of residual vector at each iteration, print rnorm and rnorm1 for iterative refinement, print wnorm and rnorm used for Re-orthogonalization, V^T * B * (resid/B-norm(resid)), print the results of whether the current residual vector is orthogonal to the current Lanczos basis. msaitr > 3: print the matrix T at each iteration. print the residual vector and arnoldi vectors. mseigt > 0: print the current matrix T. msgets > 0: print NEV and NP, eigenvalues of and corresponding Ritz estimates of the current T matrix. msapps > 0: print information about deflation at row/column no. msapps > 1: print initial matrix T print sigmak, betak and matrix T after all shifts msapps > 2: print the matrix T after the application of each shift. msapps > 3: updated residual for next iteration. mseupd > 1: print eigenvalues of the final T matrix, the last row of the eigenvector matrix for T, if reordered, reordered last row of the eigenvector matrix, reordered NCV Ritz values of the final T matrix, if type = 'REGULAR', untransformed "converged" Ritz values and corresponding Ritz estimates, NCV Ritz values of the final T matrix, last row of the eigenvector matrix for T, if reordered, reordered last row of the eigenvector matrix, reordered NCV Ritz values of the final T. mseupd > 2: print the matrix T. ========================================= === Specific to the nonsymmetric code === ========================================= mnaupd > 0: *Print the number of iterations taken, number of "converged" eigenvalues, real and imaginary parts of the converged Ritz values and their corresponding Ritz estimates, *Print various timing statistics. mnaup2 > 0: *Print major iteration number. *Print the number of "converged" Ritz values on exit, and the real and imaginary parts of the "converged" Ritz values and corresponding Ritz estimates. mnaup2 > 1: *Print the length of the Arnoldi Factorization, and the B-norm of its residual vector. *Print NEV and NP, real and imaginary parts of the "wanted" Ritz values and associated Ritz estimates at each iteration. *Print the B-norm of the residual of the compressed factorization and the compressed upper Hessenberg matrix H. mnaup2 > 2: *Print the real and imaginary parts of all the Ritz values and associated Ritz estimates, NEV, NP, NUMCNV, NCONV. *Print the real and imaginary parts of the shifts. If the exact shift strategy is used, print the associated Ritz estimates of the shifts. *Print the real and imaginary parts of the Ritz values and the corresponding Ritz estimates obtained from _neigh. mnaitr > 0: *Print if a restart is needed. mnaitr > 1: *Print the number of Arnoldi vector being generated and the B-norm of the current residual. mnaitr > 2: *Print j-th column of the Hessenberg matrix H. *Print reorthogonalization and iterative refinement information, *Print the final upper Hessenberg matrix of order K+NEV. mnaitr > 3: *Print V^T*B*resid/(B-norm(resid)). mnaitr > 4: *Print current upper Hessenberg matrix. mnaitr > 5: *Print updated arnoldi vectors and the residual vector. mneigh > 1: *Print the last row of the Schur matrix for H, and the last row of the eigenvector matrix for H. mneigh > 2: *Print the entering upper Hessenberg matrix. *Print the real and imaginary part of eigenvalues of the current Hessenberg matrix, and associated Ritz estimates. mngets > 0: *Print the real and imaginary parts of the Ritz values of the Hessenberg matrix and their the corresponding error bounds, KEV, NP. mnapps > 0: *Print information about where deflation occured. mnapps > 1: *Print sigmak, betak, order of the final Hessenberg matrix, and the final compressed upper Hessenberg matrix. mnapps > 2: *Print implicit application of shift number, real and imaginary part of the shift. *Print the indices of the submatrix that the shift is applied. mnapps > 3: *Print the matrix H before and after the application of each shift, updated residual for next iteration. mnapps > 4: *Print the accumulated orthogonal Hessenberg matrix Q, updated matrix of Arnoldi vectors. mneupd > 0: *Print the number of converged Ritz values, B-norm of the residual, all NCV Ritz values and error bounds. mneupd > 1: *Print the final upper Hessenberg matrix computed by _naupd. *If Ritz vectors are requested, print real and imaginary parts of the eigenvalues and the last row of the Schur vectors as computed by _neupd. mneupd > 2: *If Ritz vectors are requested, print the threshold eigenvalue used for re-ordering. *If Ritz vectors are requested, print the number of eigenvalues to reorder and the number of converged Ritz values. *If Ritz vectors are requested, print the upper quasi-matrix computed by _neupd. *If Ritz vectors are requested, print the real and imaginary part of the Ritz values. *If Ritz vectors are requested, print the last row of the eigenvector matrix. *Print the NCV Ritz estimates in the original system. mneupd > 3: *Print the integer array of pointers. *If Ritz vectors are requested, print the eigenvector matrix. *If Ritz vectors are requested, print the reordered upper quasi-triangular matrix. mneupd > 4: *If Ritz vectors are requested, print the Q matrix of the QR factorization of the matrix representing the wanted invariant subspace. *If Ritz vectors are requested, print the Schur vectors. *If Ritz vectors are requested, print the reordered Schur vectors. ==================================== === Specific to the complex code === ==================================== mcaupd > 0: *Print the number of iterations taken, number of "converged" eigenvalues, the converged Ritz values and their corresponding Ritz estimates, *Print various timing statistics. mcaup2 > 0: *Print major iteration number. *Print the number of "converged" Ritz values on exit, and the "converged" Ritz values and corresponding Ritz estimates. mcaup2 > 1: *Print the length of the Arnoldi Factorization, and the B-norm of its residual vector. *Print NEV and NP, the "wanted" Ritz values and associated Ritz estimates at each iteration. *Print the B-norm of the residual of the compressed factorization and the compressed upper Hessenberg matrix H. mcaup2 > 2: *Print the all the Ritz values and associated Ritz estimates, NEV, NP, NUMCNV, NCONV. *Print the shifts. If the exact shift strategy is used, print the associated Ritz estimates of the shifts. *Print the Ritz values and the corresponding Ritz estimates obtained from _neigh. mcaitr > 0: *Print if a restart is needed. mcaitr > 1: *Print the number of Arnoldi vector being generated and the B-norm of the current residual. mcaitr > 2: *Print j-th column of the Hessenberg matrix H. *Print reorthogonalization and iterative refinement information, *Print the final upper Hessenberg matrix of order K+NEV. mcaitr > 3: *Print V^T*B*resid/(B-norm(resid)). mcaitr > 4: *Print current upper Hessenberg matrix. mcaitr > 5: *Print updated Arnoldi vectors and the residual vector. mceigh > 1: *Print the last row of the Schur matrix for H, and the last row of the eigenvector matrix for H. mceigh > 2: *Print the entering upper Hessenberg matrix. *Print the eigenvalues of the current Hessenberg matrix, and associated Ritz estimates. mcgets > 0: *Print the real and imaginary parts of the Ritz values of the Hessenberg matrix and their the corresponding error bounds, KEV, NP. mcapps > 0: *Print information about where deflation occured. mcapps > 1: *Print sigmak, betak, order of the final Hessenberg matrix, and the final compressed upper Hessenberg matrix. mcapps > 2: *Print implicit application of shift number, the shift. *Print the indices of the submatrix that the shift is applied. mcapps > 3: *Print the matrix H before and after the application of each shift, updated residual for next iteration. mcapps > 4: *Print the accumulated unitary Hessenberg matrix Q, and the updated matrix of Arnoldi vectors. mceupd > 0: *Print the number of converged Ritz values, B-norm of the residual, all NCV Ritz values and error bounds. mceupd > 1: *Print the final upper Hessenberg matrix computed by _naupd. *If Ritz vectors are requested, print the eigenvalues and the last row of the Schur vectors as computed by _neupd. mceupd > 2: *If Ritz vectors are requested, print the threshold eigenvalue used for re-ordering. *If Ritz vectors are requested, print the number of eigenvalues to reorder and the number of converged Ritz values. *If Ritz vectors are requested, print the upper quasi-matrix computed by _neupd. *If Ritz vectors are requested, print the Ritz values. *If Ritz vectors are requested, print the last row of the eigenvector matrix. *Print the NCV Ritz estimates in the original system. mceupd > 3: *Print the integer array of pointers. *If Ritz vectors are requested, print the eigenvector matrix. mceupd > 4: *If Ritz vectors are requested, print the Q matrix of the QR factorization of the matrix representing the wanted invariant subspace. *If Ritz vectors are requested, print the Schur vectors. arpack-ng-3.3.0/DOCUMENTS/ex-complex.doc000066400000000000000000000130701260666001200174710ustar00rootroot00000000000000c----------------------------------------------------------------------- c c\Example-1 c ... Suppose want to solve A*x = lambda*x in regular mode c ... so OP = A and B = I. c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 1 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, rwork, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, rwork, info ) c stop c end c c\Example-2 c ... Suppose want to solve A*x = lambda*x in shift-invert mode c ... so OP = inv[A - sigma*I] and B = I c ... Assume "call solve(n,rhs,x)" solves [A - sigma*I]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iaparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, rwork, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call solve (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, rwork, info ) c stop c end c c\Example-3 c ... Suppose want to solve A*x = lambda*M*x in regular mode c ... so OP = inv[M]*A and B = M. c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume "call solveM(n,rhs,x)" solves M*x = rhs c ... Assume user will supplied shifts c ... c ido = 0 c iparam(7) = 2 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, rwork, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), temp_array) c call solveM (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c c ... delete this last conditional if want to use exact shifts c else if (ido .eq. 3) then c ... compute shifts and put in workl starting from the position c ... pointed by ipntr(14). c np = iparam(8) c call scopy (np, shifts, 1, workl(ipntr(14), 1) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, rwork, info ) c stop c end c c\Example-4 c ... Suppose want to solve A*x = lambda*M*x in shift-invert mode c ... so OP = inv[A - sigma*M]*M and B = M c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, rwork, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), temp_array) c call solve (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, rwork, info ) c stop c end c\EndDoc arpack-ng-3.3.0/DOCUMENTS/ex-nonsym.doc000066400000000000000000000224121260666001200173450ustar00rootroot00000000000000c----------------------------------------------------------------------- c c\Example-1 c ... Suppose want to solve A*x = lambda*x in regular mode c ... so OP = A and B = I. c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 1 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c stop c end c c\Example-2 c ... Suppose want to solve A*x = lambda*x in shift-invert mode c ... so OP = inv[A - sigma*I] and B = I, sigma has zero c ... imaginary part c ... Assume "call solve(n,rhs,x)" solves [A - sigma*I]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iaparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call solve (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c stop c end c c\Example-3 c ... Suppose want to solve A*x = lambda*M*x in regular mode c ... so OP = inv[M]*A and B = M. c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume "call solveM(n,rhs,x)" solves M*x = rhs c ... Assume user will supplied shifts c ... c ido = 0 c iparam(7) = 2 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), temp_array) c call solveM (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c c ... delete this last conditional if want to use exact shifts c else if (ido .eq. 3) then c ... compute shifts and put in workl starting from the position c ... pointed by ipntr(14). c np = iparam(8) c call scopy (np, shifts, 1, workl(ipntr(14), 1) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c stop c end c c\Example-4 c ... Suppose want to solve A*x = lambda*M*x in shift-invert mode c ... so OP = inv[A - sigma*M]*M and B = M, sigma has zero c ... imaginary part c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), temp_array) c call solve (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c stop c end c c\Example-5 c ... Suppose want to solve A*x = lambda*M*x in shift-invert mode c ... So OP = Real_Part{inv[A-SIGMA*M]*M and B=M, sigma has c ... nonzero imaginary part c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... in complex arithmetic c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), temp_array) c call solve(n, temp_array, complex_array) c do i = 1, n c workd(ipntr(2)+i-1) = real(complex_array(i)) c end do c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), complex_array) c do i = 1, n c workd(ipntr(2)+i-1) = real(complex_array(i)) c end do c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess. c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c ... Use Rayleigh quotient to transform d(:,1) and d(:,2) c to the approximation to the original problem. c stop c end c c\Example-6 c ... Suppose want to solve A*x = lambda*M*x in shift-invert mode c ... So OP = Imaginary_Part{inv[A-SIGMA*M]*M and B=M, sigma must c ... have nonzero imaginary part c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... in complex arithmetic c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _naupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, c & iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), temp_array) c call solve(n, temp_array, complex_array) c do i = 1, n c workd(ipntr(2)+i-1) = aimag(complex_array(i)) c end do c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), complex_array) c do i = 1, n c workd(ipntr(2)+i-1) = aimag(complex_array(i)) c end do c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _neupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _neupd ( rvec, 'All', select, d, d(1,2), v, ldv, c & sigmar, sigmai, workev, bmat, n, which, nev, tol, c & resid, ncv, v, ldv, iparam, ipntr, workd, workl, c & lworkl, info ) c ... Use Rayleigh quotient to transform d(:,1) and d(:,2) c to the Ritz approximation to the original problem. c stop c end c c\EndDoc arpack-ng-3.3.0/DOCUMENTS/ex-sym.doc000066400000000000000000000212051260666001200166310ustar00rootroot00000000000000c----------------------------------------------------------------------- c c\Example-1 c ... Suppose want to solve A*x = lambda*x in regular mode c ... so OP = A and B = I. c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 1 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... Call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c c stop c end c c\Example-2 c ... Suppose want to solve A*x = lambda*x in shift-invert mode c ... so OP = inv[A - sigma*I] and B = I. c ... Assume "call solve(n,rhs,x)" solves [A - sigma*I]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'I', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call solve (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... Call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c c\Example-3 c ... Suppose want to solve A*x = lambda*M*x in regular mode c ... so OP = inv[M]*A and B = M. c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume "call solveM(n,rhs,x)" solves M*x = rhs c ... Assume user will supplied shifts c ... c ido = 0 c iparam(7) = 2 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), temp_array) c call _scopy (n, temp_array, 1, workd(ipntr(1)), 1) c call solveM (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c c ... delete this last conditional if want to use exact shifts c else if (ido .eq. 3) then c ... compute shifts and put in the first np locations of work c np = iparam(8) c call _copy (np, shifts, 1, workl(ipntr(11), 1) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c stop c end c c\Example-4 c ... Suppose want to solve A*x = lambda*M*x in shift-invert mode c ... so OP = (inv[A - sigma*M])*M and B = M. c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 3 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), temp_array) c call solve (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c c stop c end c c\Example-5 c ... Suppose want to solve K*x = lambda*KG*x in Buckling mode c ... so OP = (inv[K - sigma*KG])*K and B = K. c ... Assume "call matvecM(n,x,y)" computes y = KG*x c ... Assume "call matvecA(n,x,y)" computes y = K*x c ... Assume "call solve(n,rhs,x)" solves [K - sigma*KG]*x = rhs c ... Assume exact shifts are used c c ido = 0 c iparam(7) = 4 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecA (n, workd(ipntr(1)), temp_array) c solve (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 1) then c call solve (n, workd(ipntr(3)), workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecA (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c stop c end c c\Example-6 c ... Suppose want to solve A*x = lambda*M*x in Cayley mode c ... so OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ... Assume "call matvecM(n,x,y)" computes y = M*x c ... Assume "call matvecA(n,x,y)" computes y = A*x c ... Assume "call solve(n,rhs,x)" solves [A - sigma*M]*x = rhs c ... Assume exact shifts are used c ... c ido = 0 c iparam(7) = 5 c c %------------------------------------% c | Beginning of reverse communication | c %------------------------------------% c 10 continue c call _saupd ( ido, 'G', n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c call matvecA (n, workd(ipntr(1)), temp_array) c call _axpy (n, sigma, workd(inptr(2)), 1, temp_array, 1) c call solve (n, temp_array, workd(ipntr(2))) c go to 10 c else if (ido .eq. 1) then c call matvecA (n, workd(ipntr(1)), workd(ipntr(2))) c call _axpy (n, sigma, workd(inptr(3)), 1, workd(ipntr(2)), 1) c call _copy (n, workd(inptr(2)), 1, workd(ipntr(3)), 1) c call solve (n, workd(ipntr(3)), workd(ipntr(2))) c go to 10 c else if (ido .eq. 2) then c call matvecM (n, workd(ipntr(1)), workd(ipntr(2))) c go to 10 c end if c %------------------------------% c | End of Reverse communication | c %------------------------------% c c ... call _seupd to postprocess c ... want the Ritz vectors set rvec = .true. else rvec = .false. c call _seupd ( rvec, 'All', select, d, z, ldz, sigma, bmat, c & n, which, nev, tol, resid, ncv, v, ldv, iparam, c & ipntr, workd, workl, lworkl, info ) c stop c end c\EndDoc c arpack-ng-3.3.0/DOCUMENTS/stat.doc000066400000000000000000000065521260666001200163720ustar00rootroot00000000000000c----------------------------------------------------------------------- c c Include this file to get timing statistics for the different parts c of the Arnoldi update iteration. An easy way to initialize all the c timing information to zero at the beginning is by: c c call sstats <-- symmetric code c call sstatn <-- nonsymmetric code c call cstatn <-- complex code c c----------------------------------------------------------------------- c c nopx = total number of user OP*x operation c nbx = total number of user B*x operation (same as copy when B = I) c nrorth = total number of reorthogonalization steps taken c nitref = total number of it. refinement steps in reorthogonalization c nrstrt = total number of restart steps c c----------------------------------------------------------------------- c c======================================================== c=== Common to both symmetric and nonsymmetric code === c======================================================== c c tgetv0 = total time spent in generating starting vector and c restarted vector for the Arnoldi sequence. c titref = total time spent in iterative refinement phase in SSAITR. c trvec = total time spent in computing the Ritz vectors before exit. c c==================================== c=== Specific to symmetric code === c==================================== c c tsaupd = total time spent in SSAUPD. c tsaup2 = total time spent in SSAUP2. c tsaitr = total time spent in the basic Arnoldi iteration loop, c including iterative refinement in SSAITR. c tseigt = total time spent in computing the tridiagonal eigenvalue c subproblem at each iteration. c tsgets = total time spent in getting the shifts at each iteration. c tsapps = total time spent in applying the shifts at each iteration. c tsconv = total time spent in convergence test at each iteration. c c======================================= c=== Specific to nonsymmetric code === c======================================= c c tnaupd = total time spent in SNAUPD. c tnaup2 = total time spent in SNAUP2. c tnaitr = total time spent in the basic Arnoldi iteration loop, c including iterative refinement in SNAITR. c tneigh = total time spent in computing the Hessenberg eigenvalue c subproblem at each iteration. c tngets = total time spent in getting the shifts at each iteration. c tnapps = total time spent in applying the shifts at each iteration. c tnconv = total time spent in convergence test at each iteration. c c================================== c=== Specific to complex code === c================================== c c tcaupd = total time spent in CNAUPD. c tcaup2 = total time spent in CNAUP2. c tcaitr = total time spent in the basic Arnoldi iteration loop, c including iterative refinement in CNAITR. c tceigh = total time spent in computing the Hessenberg eigenvalue c subproblem at each iteration. c tcgets = total time spent in getting the shifts at each iteration. c tcapps = total time spent in applying the shifts at each iteration. c tcconv = total time spent in convergence test at each iteration. c c================== c=== User time === c================== c c tmvopx = total time spent in computing Y = OP * X c tmvbx = total time spent in computing Y = B * X c c======================================================================= c arpack-ng-3.3.0/EXAMPLES/000077500000000000000000000000001260666001200145755ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/BAND/000077500000000000000000000000001260666001200153015ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/BAND/Makefile.am000066400000000000000000000037011260666001200173360ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SSBDR = ssbdr1 ssbdr2 ssbdr3 ssbdr4 ssbdr5 ssbdr6 DSBDR = dsbdr1 dsbdr2 dsbdr3 dsbdr4 dsbdr5 dsbdr6 SNBDR = snbdr1 snbdr2 snbdr3 snbdr4 snbdr5 snbdr6 DNBDR = dnbdr1 dnbdr2 dnbdr3 dnbdr4 dnbdr5 dnbdr6 CNBDR = cnbdr1 cnbdr2 cnbdr3 cnbdr4 ZNBDR = znbdr1 znbdr2 znbdr3 znbdr4 BAND = $(SSBDR) $(DSBDR) $(SNBDR) $(DNBDR) $(CNBDR) $(ZNBDR) check_PROGRAMS = $(BAND) TESTS = $(check_PROGRAMS) EXTRA_DIST = README # Simple symetric problem using BAND solver (single precision) ssbdr1_SOURCES = ssbdr1.f ssband.f ssbdr2_SOURCES = ssbdr2.f ssband.f ssbdr3_SOURCES = ssbdr3.f ssband.f ssbdr4_SOURCES = ssbdr4.f ssband.f ssbdr5_SOURCES = ssbdr5.f ssband.f ssbdr6_SOURCES = ssbdr6.f ssband.f # Simple symmetric problem using BAND solver (double precision) dsbdr1_SOURCES = dsbdr1.f dsband.f dsbdr2_SOURCES = dsbdr2.f dsband.f dsbdr3_SOURCES = dsbdr3.f dsband.f dsbdr4_SOURCES = dsbdr4.f dsband.f dsbdr5_SOURCES = dsbdr5.f dsband.f dsbdr6_SOURCES = dsbdr6.f dsband.f # Simple nonsymmetric problem using BAND solver (single precision) snbdr1_SOURCES = snbdr1.f snband.f snbdr2_SOURCES = snbdr2.f snband.f snbdr3_SOURCES = snbdr3.f snband.f snbdr4_SOURCES = snbdr4.f snband.f snbdr5_SOURCES = snbdr5.f snband.f snbdr6_SOURCES = snbdr6.f snband.f # Simple nonsymmetric problem using BAND solver (double precision) dnbdr1_SOURCES = dnbdr1.f dnband.f dnbdr2_SOURCES = dnbdr2.f dnband.f dnbdr3_SOURCES = dnbdr3.f dnband.f dnbdr4_SOURCES = dnbdr4.f dnband.f dnbdr5_SOURCES = dnbdr5.f dnband.f dnbdr6_SOURCES = dnbdr6.f dnband.f # Complex problem using BAND solver (single precision complex) cnbdr1_SOURCES = cnbdr1.f cnband.f cnbdr2_SOURCES = cnbdr2.f cnband.f cnbdr3_SOURCES = cnbdr3.f cnband.f cnbdr4_SOURCES = cnbdr4.f cnband.f # Complex problem using BAND solver (double precision complex) znbdr1_SOURCES = znbdr1.f znband.f znbdr2_SOURCES = znbdr2.f znband.f znbdr3_SOURCES = znbdr3.f znband.f znbdr4_SOURCES = znbdr4.f znband.f arpack-ng-3.3.0/EXAMPLES/BAND/README000066400000000000000000000045741260666001200161730ustar00rootroot000000000000001. Purpose ------- This directory contains example drivers that call subroutines [s,d]sband.f, [s,d]nband.f or [c,z]nband.f to solve various eigenvalue problems in which matrices have BANDED structure. These drivers illustrate how to construct LAPACK-style banded matrices, and how to set various ARPACK parameters to solve different problems in different modes. The user may modify any one of these drivers, and construct his/her own matrix to solve the problem of his/her own interest. 2. Naming convention ----------------- The name for each banded solver has the form 'XYband.f', where X - is 's' (single precision) or 'd' (double precision) or 'c' (single precision complex) or 'z' (double precision complex) Y - is 's' (symmetric) or 'n' (nonsymmetric) The name for each driver has the form 'XYbdrN.f', where X - is 's' (single precision) or 'd' (double precision) or 'c' (single precision complex) or 'z' (double precision complex) Y - is 's' (symmetric) or 'n' (nonsymmetric) N - is a number between 1 and 6. If N = 1, the driver solves a STANDARD eigenvalue problem in REGULAR mode. N = 2, the driver solves a STANDARD eigenvalue problem in SHIFT-INVERT mode. N = 3, the driver solves a GENERALIZED eigenvalue problem in INVERSE mode. N = 4, the driver solves a GENERALIZED eigenvalue problem in SHIFT-INVERT mode (using mode 3 of __aupd.) These are four commonly used drivers. When N > 4 (only for real matrices), a special mode is used. For symmetric problem, if N = 5, the driver solves a GENERALIZED eigenvalue problem in BUCKLING mode. N = 6, the driver solves a GENERALIZED eigenvalue problem in CAYLEY mode. For nonsymmetric problem, if N = 5, the driver solves a STANDARD eigenvalue problem in SHIFT-INVERT mode using mode 4 of [d,s]naupd.f. N = 6. the driver solves a GENERALIZED eigenvalue problem SHIFT-INVERT mode using mode 4 of [d,s]naupd.f. Note: the imaginary part of the shift MUST be nonzero when these two drivers are used. 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make snbdr1". Then execute using "snbdr1". arpack-ng-3.3.0/EXAMPLES/BAND/cnband.f000066400000000000000000000550701260666001200167040ustar00rootroot00000000000000c \BeginDoc c c \Name: cnband c c \Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style banded form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Schur basis. c c cnband can be called with one of the following modes: c c Mode 1: A*z = lambda*z. c ===> OP = A and B = I. c c Mode 2: A*z = lambda*M*z, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c c Mode 3: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode. c c Choice of different modes can be specified in IPARAM(7) defined below. c c \Usage c call cnband c ( RVEC, HOWMNY, SELECT, D , Z, LDZ, SIGMA, WORKEV, N, AB, c MB, LDA, FAC, KL, KU, WHICH, BMAT, NEV, TOL, RESID, NCV, c V, LDV, IPARAM, WORKD, WORKL, LWORKL, RWORK, IWORK, INFO ) c c \Arguments c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the invariant subspace to be computed c corresponding to the converged Ritz values. c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the real Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV columns of the c array V. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex work array of dimension NCV. (WORKSPACE) c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Complex array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Complex array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array MB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7)=1. c c LDA Integer. (INPUT) c Leading dimension of AB, MB, FAC. c c FAC Complex array of LDA by N. (WORKSPACE/OUTPUT) c FAC is used to store the LU factors of MB when mode 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when mode 3 is invoked. c It is not referenced when IPARAM(7)=1. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When mode 1,2 are used, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c When mode 3 is used, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c NEV Integer. (INPUT) c Number of eigenvalues of to be computed. c c TOL Real scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = slamch('EPS') (machine precision as computed c by the LAPACK auxilliary subroutine slamch). c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c c V Complex array N by NCV. (OUTPUT) c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then c the first NCONV=IPARAM(5) columns of V will contain Ritz vectors c of the eigensystem A*z = lambda*B*z. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. LDV must be great than or equal to N. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ---------------------------------------------------------- c ISHIFT = 1: exact shift with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ------------------------------------------------------------- c c IPARAM(2) = Not referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c c IPARAM(6) = IUPD c Not referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2 or 3; See under \Description of cnband for the c three modes available. c c WORKD Complex work array of length at least 3*n. (WORKSPACE) c c WORKL Complex work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Real array of length N (WORKSPACE) c Workspace used in cnaupd. c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used to mode 2,3. Store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: CNAUPD did not find any eigenvalues to sufficient c accuracy. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\Routines called c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgbtrf LAPACK band matrix factorization routine. c cgbtrs LAPACK band linear system solve routine. c clacpy LAPACK matrix copy routine. c ccopy Level 1 BLAS that copies one vector to another. c scnrm2 Level 1 BLAS that computes the norm of a vector. c cgbmv Level 2 BLAS that computes the band matrix vector product. c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine cnband(rvec, howmny, select, d , z, ldz, sigma, & workev, n, ab, mb, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info ) c c %------------------% c | Scalar Arguments | c %------------------% c Character which*2, bmat, howmny Logical rvec Integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Complex & sigma Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c Integer iparam(*), iwork(*) Logical select(*) Complex & d(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), fac(lda,*), & workd(*), workl(*), workev(*) Real & rwork(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, mode, ierr, itop, imid, ibot c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) ) c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Real & scnrm2 external ccopy, cgbmv, cgbtrf, cgbtrs, scnrm2, clacpy c c %-----------------------% c | Executable Statements | c %-----------------------% c mode = iparam(7) c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( mode .eq. 2 ) then c c %-----------------------------------------------% c | Copy M to fac and Call LAPACK routine cgbtrf | c | to factor M. | c %-----------------------------------------------% c call clacpy ('A', ibot, n, mb, lda, fac, lda ) call cgbtrf(n, n, kl, ku, fac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_band: error in _gbtrf' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c if (bmat .eq. 'I') then c c %-------------------------% c | Construct (A - sigma*I) | c %-------------------------% c call clacpy ('A', ibot, n, ab, lda, fac, lda ) do 10 j = 1,n fac(imid,j) = ab(imid,j) - sigma 10 continue c else c c %---------------------------% c | Construct (A - sigma*M) | c %---------------------------% c do 30 j = 1,n do 20 i = itop, ibot fac(i,j) = ab(i,j) - sigma*mb(i,j) 20 continue 30 continue c end if c c %------------------------% c | Factor (A - sigma*M) | c %------------------------% c call cgbtrf(n, n, kl, ku, fac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_band: error in _gbtrf.' print*, ' ' go to 9000 end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 40 continue c call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1) then c if ( mode .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( mode .eq. 2 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call cgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in sbgtrs.' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*M* x c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call cgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c end if c else if (ido .eq. 1) then c if ( mode .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( mode .eq. 2 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call cgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), ldv, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in sbgtrs.' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c if ( bmat .eq. 'I' ) then c c %----------------------------------% c | Perform y <-- inv(A-sigma*I)*x. | c %----------------------------------% c call ccopy(n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call cgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c else c c %--------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %--------------------------------------% c call ccopy(n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call cgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c end if c endif c else if (ido .eq. 2) then c c %--------------------% c | Perform y <-- M*x | c %--------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else c c %-------------------------------------------% c | Either we have convergence, or there is | c | error. | c %-------------------------------------------% c if ( info .ne. 0) then c c %--------------------------% c | Error message, check the | c | documentation in dnaupd | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd ' print *, ' ' c else c call cneupd (rvec, howmny , select, d, z, ldz, sigma, & workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, rwork, info) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of cneupd. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' c endif c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call cnaupd again. | c %----------------------------------------% c go to 40 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/cnbdr1.f000066400000000000000000000247631260666001200166350ustar00rootroot00000000000000 program cnbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call CNBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 1 of CNAUPD. c c\BeginLib c c cnband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c claset LAPACK routine to initialize a matrix to zero. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c scnrm2 Level 1 BLAS that computes the norm of a vector. c cgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr1.F SID: 2.3 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, i, j, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv logical rvec Real & tol Complex & rho, h, h2, sigma c c %------------% c | Parameters | c %------------% c Complex & one, zero, two parameter ( one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, cgbmv, caxpy, slapy2, claset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV and WHICH to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. Setting INFO=0 indicates that a | c | random vector is generated in CNAUPD to start the | c | Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of CNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details, see the documentation | c | in cnband. | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call claset('A', lda, n, zero, zero, a, lda) call claset('A', lda, n, zero, zero, m, lda) call claset('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / cmplx(nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (4.0E+0, 0.0E+0) / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = (1.0E+2, 0.0E+0) isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call cnband(rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR1 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv c c %---------------------------% c | Compute the residual norm | c | || A*x - lambda*x || | c %---------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call caxpy(n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 90 continue call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for cnband. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/cnbdr2.f000066400000000000000000000252051260666001200166260ustar00rootroot00000000000000 program cnbdr2 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call CNBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 3 of CNAUPD. c c\BeginLib c c cnband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c claset LAPACK routine to initialize a matrix to zero. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c scnrm2 Level 1 BLAS that computes the norm of a vector. c cgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr2.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, i, j, & n, nxi, lo, isub, isup, idiag, maxitr, mode, & nconv logical rvec Real & tol Complex & rho, h, h2, sigma c c %------------% c | Parameters | c %------------% c Complex & one, zero, two parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, cgbmv, caxpy, slapy2, claset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to SIGMA) to be | c | approximated. Since the shift and invert mode | c | is used, WHICH is set to 'LM'. The user can | c | modify NX, NEV and NCV to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nxi = 10 n = nxi*nxi nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. Setting INFO=0 indicates that a | c | random vector is generated in CNAUPD to start the | c | Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of CNAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in cnband. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call claset('A', lda, n, zero, zero, a, lda) call claset('A', lda, n, zero, zero, m, lda) call claset('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nxi ku = nxi c c %---------------% c | Main diagonal | c %---------------% c h = one / cmplx(nxi+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (4.0E+0, 0.0E+0) / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = (1.0E+2, 0.0E+0) isup = kl+ku isub = kl+ku+2 do 50 i = 1, nxi lo = (i-1)*nxi do 40 j = lo+1, lo+nxi-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nxi-1 lo = (i-1)*nxi do 70 j = lo+1, lo+nxi a(isup,nxi+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call cnband(rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR2 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv c c %---------------------------% c | Compute the residual norm | c | || A*x - lambda*x || | c %---------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call caxpy(n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 90 continue call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for cnband. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/cnbdr3.f000066400000000000000000000242731260666001200166330ustar00rootroot00000000000000 program cnbdr3 c c ... Construct matrices A and M in LAPACK-style band form. c Matrices A and M are derived from the finite c element discretization of the 1-dimensional c convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... Call CNBAND to find eigenvalues LAMBDA such that c A*x = M*x*LAMBDA. c c ... Eigenvalues with largest real parts are sought. c c ... Use mode 2 of CNAUPD. c c\BeginLib c c\Routines called: c cnband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c claset LAPACK routine to initialize a matrix to zero. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c scnrm2 Level 1 BLAS that computes the norm of a vector. c cgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr3.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn), mx(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, & n, idiag, isup, isub, maxitr, & mode, nconv logical rvec Real & tol Complex & rho, h, sigma c c %------------% c | Parameters | c %------------% c Complex & one, zero, two parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, cgbmv, caxpy, slapy2, claset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV and WHICH to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. Setting INFO=0 indicates that | c | using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv info = 0 tol = 0.0 c c %---------------------------------------------------% c | IPARAm(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of CNAUPD is used | c | (IPARAm(7) = 2). All these options can be changed | c | by the user. For details, see the documentation | c | in cnband. | c %---------------------------------------------------% c maxitr = 300 mode = 2 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call claset('A', lda, n, zero, zero, a, lda) call claset('A', lda, n, zero, zero, m, lda) call claset('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / cmplx(n+1) c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (2.0E+0, 0.0E+0) / h m(idiag,j) = (4.0E+0, 0.0E+0) * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = (1.0E+1, 0.0E+0) do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h m(isub,j) = one*h 40 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call cnband(rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR3 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c do 50 j = 1, nconv c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call cgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call caxpy(n, -d(j), mx, 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1), rd(j,2)) 50 continue call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for cnband. | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/cnbdr4.f000066400000000000000000000245111260666001200166270ustar00rootroot00000000000000 program cndrv4 c c ... Construct matrices A and M in LAPACK-style band form. c Matries A and M are derived from the finite c element discretization of the 1-dimensional c convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... Call CNBAND to find eigenvalues LAMBDA such that c A*x = M*x*LAMBDA. c c ... Use mode 3 of CNAUPD. c c\BeginLib c c\Routines called: c cnband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c claset LAPACK routine to initialize a matrix to zero. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c scnrm2 Level 1 BLAS that computes the norm of a vector. c cgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn), mx(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, & n, idiag, isup, isub, maxitr, mode, & nconv logical rvec Real & tol Complex & rho, h, sigma c c %------------% c | Parameters | c %------------% c Complex & one, zero, two, four, six parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) , & four = (4.0E+0, 0.0E+0) , & six = (6.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, cgbmv, caxpy, slapy2, claset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV is the number of | c | eigenvalues (closest to the shift SIGMA) to be | c | approximated. Since the shift and invert mode | c | is used, WHICH is set to 'LM'. The user can | c | modify NX, NEV and NCV to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = (1.0E+1, 0.0E+0) c c %----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. Setting INFO=0 indicates that | c | we using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv info = 0 tol = 0.0 c c %---------------------------------------------------% c | IPARAm(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of CNAUPD is used | c | (IPARAm(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in cnband. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call claset('A', lda, n, zero, zero, a, lda) call claset('A', lda, n, zero, zero, m, lda) call claset('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / cmplx(n+1) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = four * h / six 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = (1.0E+1, 0.0E+0) do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h / six m(isub,j) = one*h / six 40 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call cnband(rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR4 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c do 90 j = 1, nconv c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c call cgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call cgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call caxpy(n, -d(j), mx, 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1), rd(j,2)) 90 continue call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for cnband. | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnband.f000066400000000000000000001454711260666001200167120ustar00rootroot00000000000000c \BeginDoc c c \Name: dnband c c \Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style banded form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c dnband can be called with one of the following modes: c c Mode 1: A*z = lambda*z. c ===> OP = A and B = I. c c Mode 2: A*z = lambda*M*z, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c c Mode 3: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*z = amu*z, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*z = amu*z, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c c The choice of mode must be specified in IPARAM(7) defined below. c c \Usage c call dnband c ( RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, V, N, AB, MB, LDA, RFAC, CFAC, KL, KU, WHICH, c BMAT, NEV, TOL, RESID, NCV, V, LDV, IPARAM, WORKD, c WORKL, LWORKL, WORKC, IWORK, INFO ) c c \Arguments c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Double precision array of dimension NEV+1. (OUTPUT) c On exit, DR contains the real part of the Ritz value approximations c to the eigenvalues of A*z = lambda*B*z. c c DI Double precision array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Real N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, c if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z computed by DNAUPD. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by DNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the c shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Double precision work array of dimension 3*NCV. (WORKSPACE) c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Double precision array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Double precision array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array AB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7) = 1 c c LDA Integer. (INPUT) c Leading dimension of AB, MB, RFAC and CFAC. c c RFAC Double precision array of LDA by N. (WORKSPACE/OUTPUT) c RFAC is used to store the LU factors of MB when IPARAM(7) = 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when IPARAM(7) = 3 is invoked with a real shift. c It is not referenced when IPARAM(7) = 1 or 4. c c CFAC Complex*16 array of LDA by N. (WORKSPACE/OUTPUT) c CFAC is used to store (A-SIGMA*M) and its LU factors c when IPARAM(7) = 3 or 4 are used with a complex shift SIGMA. c On exit, it contains the LU factors of (A-SIGMA*M). c It is not referenced when IPARAM(7) = 1 or 2. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When IPARAM(7)= 1 or 2, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c When IPARAM(7) = 3 or 4, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*z = lambda*z c BMAT = 'G' -> generalized eigenvalue problem A*z = lambda*M*z c NEV Integer. (INPUT) c Number of eigenvalues to be computed. c c TOL Double precision scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = DLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c Represents the dimension of the Arnoldi basis constructed c by dnaupd for OP. c c V Double precision array N by NCV+1. (OUTPUT) c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c represent approximate Schur vectors that span the c desired invariant subspace. c NOTE: The array Z may be set equal to first NEV+1 columns of the c Arnoldi basis vector array V computed by DNAUPD. In this case c if RVEC = .TRUE. and HOWMNY='A', then the first NCONV=IPARAM(5) c are the desired Ritz vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ---------------------------------------------------------- c ISHIFT = 1: exact shift with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c c IPARAM(6) = IUPD c Not referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = IPARAM(7): c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of dnband for the c four modes available. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*z operations, c NUMOPB = total number of B*z operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c WORKD Double precision work array of length at least 3*n. (WORKSPACE) c c WORKL Double precision work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c WORKC Complex*16 array of length N. (WORKSPACE) c Workspace used when IPARAM(7) = 3 or 4 for storing a temporary c complex vector. c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used when IPARAM(7)=2,3,4 to store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = 1: The Schur form computed by LAPACK routine dlahqr c could not be reordered by LAPACK routine dtrsen. c Re-enter subroutine DNEUPD with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine dlahqr. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine dtrevc. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' c = -14: DNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: Overflow occurs when we try to transform the Ritz c values returned from DNAUPD to those of the original c problem using Rayleigh Quotient. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current c Arnoldi factorization. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgbtrf LAPACK band matrix factorization routine. c dgbtrs LAPACK band linear system solve routine. c zgbtrf LAPACK complex band matrix factorization routine. c zgbtrs LAPACK complex linear system solve routine. c dlacpy LAPACK matrix copy routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlamch LAPACK routine to compute the underflow threshold. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X' denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))' * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c--------------------------------------------------------------------- c subroutine dnband( rvec, howmny, select, dr, di, z, ldz, sigmar, & sigmai, workev, n, ab, mb, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, & iparam, workd, workl, lworkl, workc, iwork, info) c c %------------------% c | Scalar Arguments | c %------------------% c character which*2, bmat, howmny integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Double precision & tol, sigmar, sigmai c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(*), iwork(*) logical select(*) Double precision & dr(*), di(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), rfac(lda,*), & workd(*), workl(*), workev(*) Complex*16 & cfac(lda,*), workc(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, type, imid, itop, ibot, ierr Double precision & numr, denr, deni, dmdul, safmin logical rvec, first c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Double precision & ddot, dnrm2, dlapy2, dlamch external ddot, dcopy, dgbmv, zgbtrf, zgbtrs, dgbtrf, & dgbtrs, dnrm2, dlapy2, dlacpy, dlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c Intrinsic dble, dimag, dcmplx c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = dlamch('safmin') c c %----------------------------------------------------------------% c | Set type of the problem to be solved. Check consistency | c | between BMAT and IPARAM(7). | c | type = 1 --> Solving standard problem in regular mode. | c | type = 2 --> Solving standard problem in shift-invert mode. | c | type = 3 --> Solving generalized problem in regular mode. | c | type = 4 --> Solving generalized problem in shift-invert mode. | c | type = 5 --> Solving standard problem in shift-invert mode | c | using iparam(7) = 4 in DNAUPD. | c | type = 6 --> Solving generalized problem in shift-invert mode. | c | using iparam(7) = 4 in DNAUPD. | c %----------------------------------------------------------------% c if ( iparam(7) .eq. 1 ) then type = 1 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'I') then type = 2 else if ( iparam(7) .eq. 2 ) then type = 3 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'G') then type = 4 else if ( iparam(7) .eq. 4 .and. bmat .eq. 'I') then type = 5 else if ( iparam(7) .eq. 4 .and. bmat .eq. 'G') then type = 6 else print*, ' ' print*, 'BMAT is inconsistent with IPARAM(7).' print*, ' ' go to 9000 end if c c %----------------------------------% c | When type = 5,6 are used, sigmai | c | must be nonzero. | c %----------------------------------% c if ( type .eq. 5 .or. type .eq. 6 ) then if ( sigmai .eq. zero ) then print*, ' ' print*, '_NBAND: sigmai must be nonzero when type 5 or 6 & is used. ' print*, ' ' go to 9000 end if end if c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( type .eq. 2 .or. type .eq. 5 ) then c c %-------------------------------% c | Solving a standard eigenvalue | c | problem in shift-invert mode. | c | Factor (A-sigma*I). | c %-------------------------------% c if (sigmai .eq. zero) then c c %-----------------------------------% c | Construct (A-sigmar*I) and factor | c | in real arithmetic. | c %-----------------------------------% c call dlacpy ('A', ibot, n, ab, lda, rfac, lda ) do 10 j = 1, n rfac(imid,j) = ab(imid,j) - sigmar 10 continue call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr ) if (ierr .ne. 0) then print*, ' ' print*, ' _NBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c else c c %-----------------------------------% c | Construct (A-sigmar*I) and factor | c | in COMPLEX arithmetic. | c %-----------------------------------% c do 30 j = 1, n do 20 i = itop, ibot cfac(i,j) = dcmplx(ab(i,j)) 20 continue 30 continue c do 40 j = 1, n cfac(imid,j) = cfac(imid,j) $ - dcmplx(sigmar, sigmai) 40 continue c call zgbtrf(n, n, kl, ku, cfac, lda, iwork, ierr ) if ( ierr .ne. 0) then print*, ' ' print*, ' _NBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c end if else if ( type .eq. 3 ) then c c %-----------------------------------------------% c | Solving generalized eigenvalue problem in | c | regular mode. Copy M to rfac, and call LAPACK | c | routine dgbtrf to factor M. | c %-----------------------------------------------% c call dlacpy ('A', ibot, n, mb, lda, rfac, lda ) call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 .or. type .eq. 6 ) then c c %-------------------------------------------% c | Solving generalized eigenvalue problem in | c | shift-invert mode. | c %-------------------------------------------% c if ( sigmai .eq. zero ) then c c %--------------------------------------------% c | Construct (A - sigma*M) and factor in real | c | arithmetic. | c %--------------------------------------------% c do 60 j = 1,n do 50 i = itop, ibot rfac(i,j) = ab(i,j) - sigmar*mb(i,j) 50 continue 60 continue c call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else c c %-----------------------------------------------% c | Construct (A - sigma*M) and factor in complex | c | arithmetic. | c %-----------------------------------------------% c do 80 j = 1,n do 70 i = itop, ibot cfac(i,j) = dcmplx( ab(i,j)-sigmar*mb(i,j), & -sigmai*mb(i,j) ) 70 continue 80 continue c call zgbtrf(n, n, kl, ku, cfac, lda, iwork, ierr) if ( ierr .NE. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 90 continue c call dnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2 ) then c if (sigmai .eq. zero) then c c %----------------------------------% c | Shift is real. Perform | c | y <--- OP*x = inv[A-sigmar*I]*x | c | to force the starting vector | c | into the range of OP. | c %----------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _bgtrs. ' print*, ' ' go to 9000 end if c else c c %--------------------------------------------% c | Shift is COMPLEX. Perform | c | y <--- OP*x = Real_Part{inv[A-sigma*I]*x} | c | to force the starting vector into the | c | range of OP. | c %--------------------------------------------% c do 100 j = 1, n workc(j) = dcmplx(workd(ipntr(1)+j-1)) 100 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 110 j = 1, n workd(ipntr(2)+j-1) = dble(workc(j)) 110 continue c end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | to force the starting vector into | c | the range of OP. | c %-----------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = Real_part{inv[A-SIGMA*M]*M}*x | c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c if ( sigmai .eq. zero ) then c c %---------------------% c | Shift is real, stay | c | in real arithmetic. | c %---------------------% c call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else c c %--------------------------% c | Goto complex arithmetic. | c %--------------------------% c do 120 i = 1,n workc(i) = dcmplx(workd(ipntr(2)+i-1)) 120 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 130 i = 1, n workd(ipntr(2)+i-1) = dble(workc(i)) 130 continue c end if c else if ( type .eq. 5) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*I]}*x | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c do 140 j = 1, n workc(j) = dcmplx(workd(ipntr(1)+j-1)) 140 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 150 j = 1, n workd(ipntr(2)+j-1) = dimag(workc(j)) 150 continue c else if ( type .eq. 6 ) then c c %----------------------------------------% c | Perform y <-- OP*x | c | Imaginary_part{inv[A-SIGMA*M]*M} | c | to force the starting vector into the | c | range of OP. | c %----------------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c do 160 i = 1,n workc(i) = dcmplx(workd(ipntr(2)+i-1)) 160 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 170 i = 1, n workd(ipntr(2)+i-1) = dimag(workc(i)) 170 continue c end if c else if (ido .eq. 1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2) then c if ( sigmai .eq. zero) then c c %----------------------------------% c | Shift is real. Perform | c | y <--- OP*x = inv[A-sigmar*I]*x. | c %----------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) else c c %------------------------------------------% c | Shift is COMPLEX. Perform | c | y <-- OP*x = Real_Part{inv[A-sigma*I]*x} | c | in COMPLEX arithmetic. | c %------------------------------------------% c do 180 j = 1, n workc(j) = dcmplx(workd(ipntr(1)+j-1)) 180 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 190 j = 1, n workd(ipntr(2)+j-1) = dble(workc(j)) 190 continue c end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %--------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %--------------------------------------% c if ( sigmai .eq. zero ) then c c %------------------------% c | Shift is real, stay in | c | real arithmetic. | c %------------------------% c call dcopy(n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else c c %---------------------------% c | Go to COMPLEX arithmetic. | c %---------------------------% c do 200 i = 1,n workc(i) = dcmplx(workd(ipntr(3)+i-1)) 200 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error in _gbtrs.' print*, ' ' go to 9000 end if c do 210 i = 1,n workd(ipntr(2)+i-1) = dble(workc(i)) 210 continue c end if c else if ( type .eq. 5 ) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*I]*x} | c %---------------------------------------% c do 220 j = 1, n workc(j) = dcmplx(workd(ipntr(1)+j-1)) 220 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 230 j = 1, n workd(ipntr(2)+j-1) = dimag(workc(j)) 230 continue c else if ( type .eq. 6) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*M]*M}*x. | c %-----------------------------------------% c do 240 i = 1,n workc(i) = dcmplx(workd(ipntr(3)+i-1)) 240 continue c call zgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 250 i = 1, n workd(ipntr(2)+i-1) = dimag(workc(i)) 250 continue c end if c else if (ido .eq. 2) then c c %--------------------% c | Perform y <-- M*x | c | Not used when | c | type = 1,2. | c %--------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else c c %-----------------------------------------% c | Either we have convergence, or there is | c | error. | c %-----------------------------------------% c if ( info .lt. 0) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd ' print *, ' ' go to 9000 c else c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c if (iparam(5) .gt. 0) then c call dneupd ( rvec, 'A', select, dr, di, z, ldz, & sigmar, sigmai, workev, bmat, n, which, & nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' go to 9000 c else if ( sigmai .ne. zero ) then c if ( type .eq. 4 .or. type .eq. 6 ) then c first = .true. do 270 j = 1, iparam(5) c c %----------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original | c | generalized eigenvalue problem. | c %----------------------------------% c if ( di(j) .eq. zero ) then c c %--------------------------------------% c | Eigenvalue is real. Compute | c | d = (x'*inv[A-sigma*M]*M*x) / (x'*x) | c %--------------------------------------% c call dgbmv('Nontranspose', n, n, kl, ku, one, $ mb(itop,1), lda, z(1,j), 1, zero, $ workd, 1) do i = 1, n workc(i) = dcmplx(workd(i)) end do call zgbtrs ('Notranspose', n, kl, ku, 1, $ cfac, lda, iwork, workc, n, info) do i = 1, n workd(i) = dble(workc(i)) workd(i+n) = dimag(workc(i)) end do denr = ddot(n, z(1,j), 1, workd, 1) deni = ddot(n, z(1,j), 1, workd(n+1), 1) numr = dnrm2(n, z(1,j), 1)**2 dmdul = dlapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar + numr*denr / dmdul else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 end if c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %-------------% c | Compute M*x | c %-------------% c call dgbmv('Nontranspose', n, n, kl, ku, $ one, mb(itop,1), lda, z(1,j), 1, zero, $ workd, 1) call dgbmv('Nontranspose', n, n, kl, ku, $ one, mb(itop,1), lda, z(1,j+1), 1, $ zero, workd(n+1), 1) do i = 1, n workc(i) = dcmplx(workd(i),workd(i+n)) end do c c %----------------------------% c | Compute inv(A-sigma*M)*M*x | c %----------------------------% c call zgbtrs('Notranspose',n,kl,ku,1,cfac, $ lda, iwork, workc, n, info) c c %-------------------------------% c | Compute x'*inv(A-sigma*M)*M*x | c %-------------------------------% c do i = 1, n workd(i) = dble(workc(i)) workd(i+n) = dimag(workc(i)) end do denr = ddot(n,z(1,j),1,workd,1) denr = denr+ddot(n,z(1,j+1),1,workd(n+1),1) deni = ddot(n,z(1,j),1,workd(n+1),1) deni = deni - ddot(n,z(1,j+1),1,workd,1) c c %----------------% c | Compute (x'*x) | c %----------------% c numr = dlapy2( dnrm2(n, z(1,j), 1), & dnrm2(n, z(1, j+1), 1) )**2 c c %----------------------------------------% c | Compute (x'x) / (x'*inv(A-sigma*M)*Mx) | c %----------------------------------------% c dmdul = dlapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar+numr*denr / dmdul di(j) = sigmai-numr*deni / dmdul first = .false. else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 c end if c else c c %---------------------------% c | Get the second eigenvalue | c | of the conjugate pair by | c | taking the conjugate of | c | previous one. | c %---------------------------% c dr(j) = dr(j-1) di(j) = -di(j-1) first = .true. c end if c 270 continue c else if ( type .eq. 2 .or. type .eq. 5) then c first = .true. do 280 j = 1, iparam(5) c c %----------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original | c | standard eigenvalue problem. | c %----------------------------------% c if ( di(j) .eq. zero ) then c c %-------------------------------------% c | Eigenvalue is real. Compute | c | d = (x'*inv[A-sigma*I]*x) / (x'*x). | c %-------------------------------------% c do i = 1, n workc(i) = dcmplx(z(i,j)) end do call zgbtrs ('Notranspose', n, kl, ku, 1, $ cfac, lda, iwork, workc, n, info) do i = 1, n workd(i) = dble(workc(i)) workd(i+n) = dimag(workc(i)) end do denr = ddot(n,z(1,j),1,workd,1) deni = ddot(n,z(1,j),1,workd(n+1),1) numr = dnrm2(n, z(1,j), 1)**2 dmdul = dlapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar + numr*denr / dmdul else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 c end if c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c do i = 1, n workc(i) = dcmplx( z(i,j), z(i,j+1) ) end do c c %---------------------------% c | Compute inv[A-sigma*I]*x. | c %---------------------------% c call zgbtrs('Notranspose',n,kl,ku,1,cfac, $ lda, iwork, workc, n, info) c c %-----------------------------% c | Compute x'*inv(A-sigma*I)*x | c %-----------------------------% c do i = 1, n workd(i) = dble(workc(i)) workd(i+n) = dimag(workc(i)) end do denr = ddot(n,z(1,j),1,workd,1) denr = denr+ddot(n,z(1,j+1),1,workd(n+1),1) deni = ddot(n,z(1,j),1,workd(n+1),1) deni = deni - ddot(n,z(1,j+1),1,workd,1) c c %----------------% c | Compute (x'*x) | c %----------------% c numr = dlapy2( dnrm2(n, z(1,j), 1), & dnrm2(n, z(1,j+1), 1))**2 c c %----------------------------------------% c | Compute (x'x) / (x'*inv(A-sigma*I)*x). | c %----------------------------------------% c dmdul = dlapy2(denr,deni)**2 if (dmdul .ge. safmin) then dr(j) = sigmar+numr*denr / dmdul di(j) = sigmai-numr*deni / dmdul first = .false. else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 end if c else c c %---------------------------% c | Get the second eigenvalue | c | of the conjugate pair by | c | taking the conjugate of | c | previous one. | c %---------------------------% c dr(j) = dr(j-1) di(j) = -di(j-1) first = .true. c end if c 280 continue c end if c end if c end if c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %----------------------------------------% c go to 90 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr1.f000066400000000000000000000274671260666001200166420ustar00rootroot00000000000000 program dnbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call DNBAND to find eigenvalues LAMBDA such that c A*x = LAMBDA*x. c c ... Use mode 1 of DNAUPD . c c\BeginLib c c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr1.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h, h2, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details, see the documentation | c | in DNBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = 1.0D+2 isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband (rvec, 'A', select, d, d(1,2), v, ldv, sigmar, sigmai, & workev, n, a, m, lda, rfac, cfac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, workd, & workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR1 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) call daxpy (n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call daxpy (n, -d(j,2), v(1,j), 1, ax, 1) call daxpy (n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2 ( d(j,3), dnrm2 (n, ax, 1) ) d(j,3) = d(j,3) / dlapy2 (d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call dmout (6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DNBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr2.f000066400000000000000000000300321260666001200166210ustar00rootroot00000000000000 program dnbdr2 c c ... Construct matrices A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Define the shift SIGMA = (SIGMAR, SIGMAI). c c ... Call DNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*x. c c ... Use mode 3 of DNAUPD . c c\BeginLib c c\Routines called: c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr2.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c--------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isub, isup, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h2, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , daxpy , dgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to (SIGMAR,SIGMAI)) to be | c | approximated. Since the shift-invert moded is | c | used, WHICH is set to 'LM'. The user can modify | c | NX, NEV, NCV, SIGMAR, SIGMAI to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 1.0D+4 sigmai = 0.0D+0 c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DNAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in DNBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0D+1 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isub,j+1) = -one/h2 + rho/two/h a(isup,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband (rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR2 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) call daxpy (n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j+1), 1, ax, 1) call daxpy (n, -d(j,2), v(1,j), 1, ax, 1) d(j,3) = dlapy2 ( d(j,3), dnrm2 (n, ax, 1) ) d(j,3) = d(j,3) / dlapy2 (d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call dmout (6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DNBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr3.f000066400000000000000000000277371260666001200166440ustar00rootroot00000000000000 program dnbdr3 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A and M are derived from the finite element c discretization of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition, c ... Call DNBAND to find eigenvalues LAMBDA such that c A*x = LAMBDA*M*x. c c ... Eigenvalues with largest real parts are sought. c c ... Use mode 2 of DNAUPD . c c\BeginLib c c\Routines called: c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr3.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. The number IDO is used for | c | reverse communication and has to be set to 0 at | c | the beginning. Setting INFO=0 indicates that we | c | using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv info = 0 tol = zero ido = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DNAUPD is used | c | (IPARAM(7) = 2). All these options can be changed | c | by the user. For details, see the documentation | c | in DNBAND . | c %---------------------------------------------------% c mode = 2 maxitr = 300 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (n+1) c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 2.0D+0 / h m(idiag,j) = 4.0D+0 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0D+1 do 50 j = 1, n a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h m(isub,j) = one*h 50 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband ( rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, A, M, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR3 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy (n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2 ( d(j,3), dnrm2 (n, ax, 1) ) d(j,3) = d(j,3) / dlapy2 (d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call dmout (6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DNBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr4.f000066400000000000000000000277271260666001200166440ustar00rootroot00000000000000 program dnbdr4 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A and M are derived from the finite element c discretization of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition. c c ... Define the shift SIGMA = (SIGMAR, SIGMAI). c c ... Call DNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*M*x. c c ... Use mode 3 of DNAUPD. c c\BeginLib c c\Routines called: c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr4.F SID: 2.6 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, six parameter (one = 1.0D+0, zero = 0.0D+0, & two = 2.0D+0, six = 6.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2, dgbmv, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 1.0D+1 sigmai = 0.0D+0 c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv info = 0 tol = zero ido = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of dnaupd is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in dnaupd. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = n iparam(7) = 3 c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset('A', lda, n, zero, zero, a, lda) call dlaset('A', lda, n, zero, zero, m, lda) call dlaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble(n+1) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 2.0D+0 / h m(idiag,j) = 4.0D+0 * h / six 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0D+1 do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h/six m(isub,j) = one*h/six 40 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, A, M, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR4 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 50 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy(n, -d(j,1), mx, 1, ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy(n, -d(j,1), mx, 1, ax, 1) call dgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 50 continue call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relatve residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr5.f000066400000000000000000000277671260666001200166510ustar00rootroot00000000000000 program dnbdr5 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A is a block tridiagonal matrix. Each c diagonal block is a tridiagonal matrix with c 4 on the diagonal, 1-rho*h/2 on the subdiagonal and c 1+rho*h/2 on the superdiagonal. Each off-diagonal block c of A is an identity matrices. c c ... Define COMPLEX shift SIGMA = (SIGMAR,SIGMAI), SIGMAI .ne. 0. c c ... Call DNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*x. c c ... Use mode 4 of DNAUPD . c c\BeginLib c c\Routines called: c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr5.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the size of each block diagonal | c | of A. The number N(=NX*NX) is the dimension of | c | the matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to (SIGMAR,SIGMAI)) to be | c | approximated. Since the shift-invert moded is | c | used, WHICH is set to 'LM'. The user can modify | c | NX, NEV, NCV, SIGMAR, SIGMAI to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 4.0D-1 sigmai = 6.0D-1 c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of DNAUPD is used | c | (IPARAM(7) = 4). All these options can be changed | c | by the user. For details, see the documentation | c | in DNBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 m(idiag,j) = 4.0D+0 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+kl+2 h = one / dble (nx+1) rho = 1.0D+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one+h*rho/two a(isub,j) = -one-h*rho/two 40 continue 50 continue c do 60 j = 1, n-1 m(isup,j+1) = one m(isub,j) = one 60 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one a(isub,j) = -one 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband (rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, ku, kl, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR5 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) call daxpy (n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j+1), 1, ax, 1) call daxpy (n, -d(j,2), v(1,j), 1, ax, 1) d(j,3) = dlapy2 ( d(j,3), dnrm2 (n, ax, 1) ) d(j,3) = d(j,3) / dlapy2 (d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call dmout (6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DNBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dnbdr6.f000066400000000000000000000316321260666001200166340ustar00rootroot00000000000000 program dnbdr6 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A is a block tridiagonal matrix. Each c diagonal block is a tridiagonal matrix with c 4 on the diagonal, 1-rho*h/2 on the subdiagonal and c 1+rho*h/2 on the superdiagonal. Each subdiagonal block c of A is an identity matrix. The matrix M is the c tridiagonal matrix with 4 on the diagonal and 1 on the c subdiagonal and superdiagonal. c c ... Define COMPLEX shift SIGMA=(SIGMAR,SIGMAI), SIGMAI .ne. zero. c c ... Call dnband to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*M*x. c c ... Use mode 4 of DNAUPD . c c\BeginLib c c\Routines called: c dnband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr6.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c--------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex*16 & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Double precision & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , & two = 2.0D+0 ) c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-----------------------------------------------------% c | The number NX is the size of each diagonal block of | c | A. The number N(=NX*NX) is the dimension of the | c | matrix. The number N(=NX*NX) is the dimension of | c | the matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV numbers of eigenvalues | c | closest to the COMPLEX shift (SIGMAR,SIGMAI) | c | (WHICH='LM') and their corresponding eigenvectors | c | are computed. The user can modify NX, NEV, NCV, | c | WHICH to solve problems of different sizes, and | c | to get different parts the spectrum. However, the | c | following rules must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0D-1 sigmai = 6.0D-1 c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of DNAUPD is used | c | (IPARAm(7) = 4). All these options can be changed | c | by the user. For details, see the documentation | c | in dnband . | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 m(idiag,j) = 4.0D+0 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 h = one / dble (nx+1) rho = 1.0D+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isub,j+1) = -one+h*rho/two a(isup,j) = -one-h*rho/two 40 continue 50 continue c do 60 j = 1, n-1 m(isub,j+1) = one m(isup,j) = one 60 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one a(isub,j) = -one 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call dnband (rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, ku, kl, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR6 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy (n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2 (n, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2 ( d(j,3), dnrm2 (n, ax, 1) ) d(j,3) = d(j,3) / dlapy2 (d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call dmout (6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for dnband . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsband.f000066400000000000000000000771621260666001200167200ustar00rootroot00000000000000c \BeginDoc c c \Name: dsband c c \Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal (Lanczos) basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style band form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are called Ritz values and Ritz vectors respectively. They are referred c to as such in the comments that follow. The computed orthonormal basis c for the invariant subspace corresponding to these Ritz values is referred c to as a Lanczos basis. c c dsband can be called with one of the following modes: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 in DSAUPD) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c The choice of mode must be specified in IPARAM(7) defined below. c c \Usage c call dsband c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, N, AB, MB, LDA, c RFAC, KL, KU, WHICH, BMAT, NEV, TOL, RESID, NCV, V, c LDV, IPARAM, WORKD, WORKL, LWORKL, IWORK, INFO ) c c \Arguments c c RVEC Logical (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the associated Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute all Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is not referenced. c c D Double precision array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by dsaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Lanczos basis array V computed by DSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Double precision (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Double precision array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Double precision array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array AB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7) = 1 c c LDA Integer. (INPUT) c Leading dimension of AB, MB, RFAC. c c RFAC Double precision array of LDA by N. (WORKSPACE/OUTPUT) c RFAC is used to store the LU factors of MB when IPARAM(7) = 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when IPARAM(7) = 3,4,5 is invoked. c It is not referenced when IPARAM(7) = 1. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When IPARAM(7)= 1 or 2, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LA' -> want the NEV eigenvalues of largest REAL part. c 'SA' -> want the NEV eigenvalues of smallest REAL part. c 'BE' -> Compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from c the high end than from the low end. c c When IPARAM(7) = 3, 4, or 5, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = DLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c Represents the dimension of the Lanczos basis constructed c by dsaupd for OP. c c V Double precision array N by NCV. (OUTPUT) c Upon INPUT: the NCV columns of V contain the Lanczos basis c vectors as constructed by dsaupd for OP. c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c represent the Ritz vectors that span the desired c invariant subspace. c NOTE: The array Z may be set equal to first NEV columns of the c Lanczos basis vector array V computed by dsaupd. In this case c if RVEC=.TRUE., the first NCONV=IPARAM(5) columns of V contain c the desired Ritz vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ------------------------------------------------------------ c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of dsband for the c five modes available. c c IPARAM(8) = NP c Not referenced. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c WORKD Double precision work array of length at least 3*n. (WORKSPACE) c c WORKL Double precision work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV. c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used when IPARAM(7)=2,3,4,5 to store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 in DSAUPD. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informational error from LAPACK routine dsteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -13: HOWMNY must be one of 'A' or 'P' c = -14: DSAUPD did not find any eigenvalues to sufficient c accuracy. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current c Arnoldi factorization. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgbtrf LAPACK band matrix factorization routine. c dgbtrs LAPACK band linear system solve routine. c dlacpy LAPACK matrix copy routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c--------------------------------------------------------------------- c subroutine dsband( rvec, howmny, select, d, z, ldz, sigma, & n, ab, mb, lda, rfac, kl, ku, which, bmat, nev, & tol, resid, ncv, v, ldv, iparam, workd, workl, & lworkl, iwork, info) c c %------------------% c | Scalar Arguments | c %------------------% c character which*2, bmat, howmny integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Double precision & tol, sigma logical rvec c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(*), iwork(*) logical select(*) Double precision & d(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), rfac(lda,*), & workd(*), workl(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, type, imid, itop, ibot, ierr c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Double precision & ddot, dnrm2, dlapy2 external ddot, dcopy, dgbmv, dgbtrf, & dgbtrs, dnrm2, dlapy2, dlacpy c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------------------% c | Set type of the problem to be solved. Check consistency | c | between BMAT and IPARAM(7). | c | type = 1 --> Solving standard problem in regular mode. | c | type = 2 --> Solving standard problem in shift-invert mode. | c | type = 3 --> Solving generalized problem in regular mode. | c | type = 4 --> Solving generalized problem in shift-invert mode. | c | type = 5 --> Solving generalized problem in Buckling mode. | c | type = 6 --> Solving generalized problem in Cayley mode. | c %----------------------------------------------------------------% c if ( iparam(7) .eq. 1 ) then type = 1 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'I') then type = 2 else if ( iparam(7) .eq. 2 ) then type = 3 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'G') then type = 4 else if ( iparam(7) .eq. 4 ) then type = 5 else if ( iparam(7) .eq. 5 ) then type = 6 else print*, ' ' print*, 'BMAT is inconsistent with IPARAM(7).' print*, ' ' go to 9000 end if c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( type .eq. 2 .or. type .eq. 6 .and. bmat .eq. 'I' ) then c c %----------------------------------% c | Solving a standard eigenvalue | c | problem in shift-invert or | c | Cayley mode. Factor (A-sigma*I). | c %----------------------------------% c call dlacpy ('A', ibot, n, ab, lda, rfac, lda ) do 10 j = 1, n rfac(imid,j) = ab(imid,j) - sigma 10 continue call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr ) if (ierr .ne. 0) then print*, ' ' print*, ' _SBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %----------------------------------------------% c | Solving generalized eigenvalue problem in | c | regular mode. Copy M to rfac and Call LAPACK | c | routine dgbtrf to factor M. | c %----------------------------------------------% c call dlacpy ('A', ibot, n, mb, lda, rfac, lda ) call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_SBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 .or. type .eq. 5 .or. type .eq. 6 & .and. bmat .eq. 'G' ) then c c %-------------------------------------------% c | Solving generalized eigenvalue problem in | c | shift-invert, Buckling, or Cayley mode. | c %-------------------------------------------% c c %-------------------------------------% c | Construct and factor (A - sigma*M). | c %-------------------------------------% c do 60 j = 1,n do 50 i = itop, ibot rfac(i,j) = ab(i,j) - sigma*mb(i,j) 50 continue 60 continue c call dgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_SBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 90 continue c call dsaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2 ) then c c %----------------------------------% c | Perform | c | y <--- OP*x = inv[A-sigma*I]*x | c | to force the starting vector | c | into the range of OP. | c %----------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _bgtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | to force the starting vector into | c | the range of OP. | c %-----------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call dcopy(n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with sbgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*M | c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 5) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*A | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call dgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 6 ) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = (inv[A-SIGMA*M])*(A+SIGMA*M)*x | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c if ( bmat .eq. 'G' ) then call dgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) call dgbmv('Notranspose', n, n, kl, ku, sigma, & mb(itop,1), lda, workd(ipntr(1)), 1, & one, workd(ipntr(2)), 1) else call dcopy(n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, sigma, & workd(ipntr(2)), 1) end if c call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c end if c else if (ido .eq. 1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2) then c c %----------------------------------% c | Perform | c | y <--- OP*x = inv[A-sigma*I]*x. | c %----------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call dcopy(n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %-------------------------------------% c call dcopy(n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 5 ) then c c %-------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*A*x | c | B*x = A*x has been computed | c | and saved in workd(ipntr(3)). | c %-------------------------------% c call dcopy (n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 6) then c c %---------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*(A+SIGMA*M)*x. | c | (M*x) has been saved in | c | workd(ipntr(3)). | c %---------------------------------% c if ( bmat .eq. 'G' ) then call dgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) call daxpy( n, sigma, workd(ipntr(3)), 1, & workd(ipntr(2)), 1 ) else call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call dgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, sigma, & workd(ipntr(2)), 1) end if call dgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c end if c else if (ido .eq. 2) then c c %----------------------------------% c | Perform y <-- B*x | c | Note when Buckling mode is used, | c | B = A, otherwise B=M. | c %----------------------------------% c if (type .eq. 5) then c c %---------------------% c | Buckling Mode, B=A. | c %---------------------% c call dgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) else call dgbmv('Notranspose', n, n, kl, ku, one, & mb(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) end if c else c c %-----------------------------------------% c | Either we have convergence, or there is | c | error. | c %-----------------------------------------% c if ( info .lt. 0) then c c %--------------------------% c | Error message, check the | c | documentation in DSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' go to 9000 c else c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c if (iparam(5) .gt. 0) then c call dseupd ( rvec, 'A', select, d, z, ldz, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of dneupd. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' go to 9000 c end if c end if c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %----------------------------------------% c go to 90 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr1.f000066400000000000000000000242201260666001200166270ustar00rootroot00000000000000 program dsbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition using standard c central difference. c c ... Call DSBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 1 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr1.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv Double precision & tol, sigma, h2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian operator on the unit square with zero | c | Dirichlet boundary condition. The number | c | N(=NX*NX) is the dimension of the matrix. A | c | standard eigenvalue problem is solved | c | (BMAT = 'I'). NEV is the number of eigenvalues | c | to be approximated. The user can modify NX,NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DSBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h2 = one / ((nx+1)*(nx+1)) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one / h2 a(isub,j) = -one / h2 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR1 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr2.f000066400000000000000000000243121260666001200166320ustar00rootroot00000000000000 program dsbdr2 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-dimensional Laplacian on the unit square c with zero Dirichlet boundary condition using standard c central difference. c c ... Call DSBAND to find eigenvalues LAMBDA closest to c SIGMA such that c A*x = x*LAMBDA. c c ... Use mode 3 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr2.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv Double precision & tol, sigma, h2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , daxpy , dgbmv c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian operator on the unit square with zero | c | Dirichlet boundary condition. The number | c | N(=NX*NX) is the dimension of the matrix. A | c | standard eigenvalue problem is solved | c | (BMAT = 'I'). NEV is the number of eigenvalues | c | (closest to the shift SIGMA) to be approximated. | c | Since the shift and invert mode is used, WHICH | c | is set to 'LM'. The user can modify NX, NEV, | c | NCV and SIGMA to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DSAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details see the documentation in | c | DSBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h2 = one / ((nx+1)*(nx+1)) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0D+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one / h2 a(isub,j) = -one / h2 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec,'A', select, d, v, ldv, sigma, n, a, m, & lda, rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR2 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call daxpy (n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr3.f000066400000000000000000000233431260666001200166360ustar00rootroot00000000000000 program dsbdr3 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call DSBAND with regular mode to find eigenvalues LAMBDA c such that c A*x = LAMBDA*M*x. c c ... Use mode 2 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr3.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Double precision & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, four, six parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 , & four = 4.0D+0 , six = 6.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , daxpy , dgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DSAUPD is used | c | (IPARAM(7) = 2). All these options can be changed | c | by the user. For details see the documentation in | c | DSBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 2 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR3 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr4.f000066400000000000000000000234321260666001200166360ustar00rootroot00000000000000 program dsbdr4 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call DSBAND with shift-invert mode to find eigenvalues LAMBDA c closest to SIGMA such that c A*x = LAMBDA*M*x. c c ... Use mode 3 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr4.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Double precision & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, four, six parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 , & four = 4.0D+0 , six = 6.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , daxpy , dgbmv c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | (closest to the shift SIGMA) to be approximated. | c | Since the shift and invert mode is used, WHICH | c | is set to 'LM'. The user can modify N, NEV, NCV | c | and SIGMA to solve problems of different sizes, | c | and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DSAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in DSBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec, 'A', select, d, v, ldv, sigma, n, a, m, & lda, rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR4 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr5.f000066400000000000000000000235011260666001200166340ustar00rootroot00000000000000 program dsbdr5 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, KG is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call DSBAND with Buckling mode to find eigenvalues LAMBDA c such that c A*x = M*x*LAMBDA. c c ... Use mode 4 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr5.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Double precision & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, four, six parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 , & four = 4.0D+0 , six = 6.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , dgbmv , daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. Since the Buckling mode is | c | is used, WHICH is set to 'LM'. The user can | c | modify N, NEV, NCV and SIGMA to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 1.0 c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of DSAUPD is used | c | (IPARAM(7) = 4). All these options can be changed | c | by the user. For details see the documentation in | c | DSBAND . | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR5 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/dsbdr6.f000066400000000000000000000234611260666001200166420ustar00rootroot00000000000000 program dsbdr6 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call DSBAND with Cayley mode to find eigenvalues LAMBDA such that c A*x = LAMBDA*M*x. c c ... Use mode 5 of DSAUPD . c c\BeginLib c c\Routines called: c dsband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK routine to initialize a matrix to zero. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr6.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Double precision & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Double precision & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, four, six parameter (one = 1.0D+0 , zero = 0.0D+0 , two = 2.0D+0 , & four = 4.0D+0 , six = 6.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2 , dnrm2 external dlapy2 , dnrm2 , daxpy , dgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. Since the Cayley mode is | c | used, WHICH is set to 'LM'. The user can | c | modify N, NEV, NCV and SIGMA to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 150.0 c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 5 of DSAUPD is used | c | (IPARAM(7) = 5). All these options can be changed | c | by the user. For details, see the documentation | c | in SBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 5 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call dlaset ('A', lda, n, zero, zero, a, lda) call dlaset ('A', lda, n, zero, zero, m, lda) call dlaset ('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dble (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call DSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call dsband ( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR6 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call dgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call dgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for DSBAND . | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snband.f000066400000000000000000001451101260666001200167170ustar00rootroot00000000000000c \BeginDoc c c \Name: snband c c \Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style banded form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c snband can be called with one of the following modes: c c Mode 1: A*z = lambda*z. c ===> OP = A and B = I. c c Mode 2: A*z = lambda*M*z, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c c Mode 3: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*z = amu*z, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*z = amu*z, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c c The choice of mode must be specified in IPARAM(7) defined below. c c \Usage c call snband c ( RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, V, N, AB, MB, LDA, RFAC, CFAC, KL, KU, WHICH, c BMAT, NEV, TOL, RESID, NCV, V, LDV, IPARAM, WORKD, c WORKL, LWORKL, WORKC, IWORK, INFO ) c c \Arguments c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Real array of dimension NEV+1. (OUTPUT) c On exit, DR contains the real part of the Ritz value approximations c to the eigenvalues of A*z = lambda*B*z. c c DI Real array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Real N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, c if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z computed by SNAUPD. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by SNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Real (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Real (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the c shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Real work array of dimension 3*NCV. (WORKSPACE) c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Real array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Real array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array AB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7) = 1 c c LDA Integer. (INPUT) c Leading dimension of AB, MB, RFAC and CFAC. c c RFAC Real array of LDA by N. (WORKSPACE/OUTPUT) c RFAC is used to store the LU factors of MB when IPARAM(7) = 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when IPARAM(7) = 3 is invoked with a real shift. c It is not referenced when IPARAM(7) = 1 or 4. c c CFAC Complex array of LDA by N. (WORKSPACE/OUTPUT) c CFAC is used to store (A-SIGMA*M) and its LU factors c when IPARAM(7) = 3 or 4 are used with a complex shift SIGMA. c On exit, it contains the LU factors of (A-SIGMA*M). c It is not referenced when IPARAM(7) = 1 or 2. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When IPARAM(7)= 1 or 2, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c When IPARAM(7) = 3 or 4, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*z = lambda*z c BMAT = 'G' -> generalized eigenvalue problem A*z = lambda*M*z c NEV Integer. (INPUT) c Number of eigenvalues to be computed. c c TOL Real scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c Represents the dimension of the Arnoldi basis constructed c by snaupd for OP. c c V Real array N by NCV+1. (OUTPUT) c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c represent approximate Schur vectors that span the c desired invariant subspace. c NOTE: The array Z may be set equal to first NEV+1 columns of the c Arnoldi basis vector array V computed by SNAUPD. In this case c if RVEC = .TRUE. and HOWMNY='A', then the first NCONV=IPARAM(5) c are the desired Ritz vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ---------------------------------------------------------- c ISHIFT = 1: exact shift with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c c IPARAM(6) = IUPD c Not referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = IPARAM(7): c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of snband for the c four modes available. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*z operations, c NUMOPB = total number of B*z operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c WORKD Real work array of length at least 3*n. (WORKSPACE) c c WORKL Real work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c WORKC Complex array of length N. (WORKSPACE) c Workspace used when IPARAM(7) = 3 or 4 for storing a temporary c complex vector. c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used when IPARAM(7)=2,3,4 to store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = 1: The Schur form computed by LAPACK routine slahqr c could not be reordered by LAPACK routine strsen. c Re-enter subroutine SNEUPD with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine slahqr. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine strevc. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' c = -14: SNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: Overflow occurs when we try to transform the Ritz c values returned from SNAUPD to those of the original c problem using Rayleigh Quotient. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current c Arnoldi factorization. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgbtrf LAPACK band matrix factorization routine. c sgbtrs LAPACK band linear system solve routine. c cgbtrf LAPACK complex band matrix factorization routine. c cgbtrs LAPACK complex linear system solve routine. c slacpy LAPACK matrix copy routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slamch LAPACK routine to compute the underflow threshold. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X' denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))' * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c--------------------------------------------------------------------- c subroutine snband( rvec, howmny, select, dr, di, z, ldz, sigmar, & sigmai, workev, n, ab, mb, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, & iparam, workd, workl, lworkl, workc, iwork, info) c c %------------------% c | Scalar Arguments | c %------------------% c character which*2, bmat, howmny integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Real & tol, sigmar, sigmai c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(*), iwork(*) logical select(*) Real & dr(*), di(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), rfac(lda,*), & workd(*), workl(*), workev(*) Complex & cfac(lda,*), workc(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, type, imid, itop, ibot, ierr Real & numr, denr, deni, dmdul, safmin logical rvec, first c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Real & sdot, snrm2, slapy2, slamch external sdot, scopy, sgbmv, cgbtrf, cgbtrs, sgbtrf, & sgbtrs, snrm2, slapy2, slacpy, slamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c Intrinsic real, aimag, cmplx c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = slamch('safmin') c c %----------------------------------------------------------------% c | Set type of the problem to be solved. Check consistency | c | between BMAT and IPARAM(7). | c | type = 1 --> Solving standard problem in regular mode. | c | type = 2 --> Solving standard problem in shift-invert mode. | c | type = 3 --> Solving generalized problem in regular mode. | c | type = 4 --> Solving generalized problem in shift-invert mode. | c | type = 5 --> Solving standard problem in shift-invert mode | c | using iparam(7) = 4 in SNAUPD. | c | type = 6 --> Solving generalized problem in shift-invert mode. | c | using iparam(7) = 4 in SNAUPD. | c %----------------------------------------------------------------% c if ( iparam(7) .eq. 1 ) then type = 1 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'I') then type = 2 else if ( iparam(7) .eq. 2 ) then type = 3 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'G') then type = 4 else if ( iparam(7) .eq. 4 .and. bmat .eq. 'I') then type = 5 else if ( iparam(7) .eq. 4 .and. bmat .eq. 'G') then type = 6 else print*, ' ' print*, 'BMAT is inconsistent with IPARAM(7).' print*, ' ' go to 9000 end if c c %----------------------------------% c | When type = 5,6 are used, sigmai | c | must be nonzero. | c %----------------------------------% c if ( type .eq. 5 .or. type .eq. 6 ) then if ( sigmai .eq. zero ) then print*, ' ' print*, '_NBAND: sigmai must be nonzero when type 5 or 6 & is used. ' print*, ' ' go to 9000 end if end if c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( type .eq. 2 .or. type .eq. 5 ) then c c %-------------------------------% c | Solving a standard eigenvalue | c | problem in shift-invert mode. | c | Factor (A-sigma*I). | c %-------------------------------% c if (sigmai .eq. zero) then c c %-----------------------------------% c | Construct (A-sigmar*I) and factor | c | in real arithmetic. | c %-----------------------------------% c call slacpy ('A', ibot, n, ab, lda, rfac, lda ) do 10 j = 1, n rfac(imid,j) = ab(imid,j) - sigmar 10 continue call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr ) if (ierr .ne. 0) then print*, ' ' print*, ' _NBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c else c c %-----------------------------------% c | Construct (A-sigmar*I) and factor | c | in COMPLEX arithmetic. | c %-----------------------------------% c do 30 j = 1, n do 20 i = itop, ibot cfac(i,j) = cmplx(ab(i,j)) 20 continue 30 continue c do 40 j = 1, n cfac(imid,j) = cfac(imid,j) $ - cmplx(sigmar, sigmai) 40 continue c call cgbtrf(n, n, kl, ku, cfac, lda, iwork, ierr ) if ( ierr .ne. 0) then print*, ' ' print*, ' _NBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c end if else if ( type .eq. 3 ) then c c %-----------------------------------------------% c | Solving generalized eigenvalue problem in | c | regular mode. Copy M to rfac, and call LAPACK | c | routine sgbtrf to factor M. | c %-----------------------------------------------% c call slacpy ('A', ibot, n, mb, lda, rfac, lda ) call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 .or. type .eq. 6 ) then c c %-------------------------------------------% c | Solving generalized eigenvalue problem in | c | shift-invert mode. | c %-------------------------------------------% c if ( sigmai .eq. zero ) then c c %--------------------------------------------% c | Construct (A - sigma*M) and factor in real | c | arithmetic. | c %--------------------------------------------% c do 60 j = 1,n do 50 i = itop, ibot rfac(i,j) = ab(i,j) - sigmar*mb(i,j) 50 continue 60 continue c call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else c c %-----------------------------------------------% c | Construct (A - sigma*M) and factor in complex | c | arithmetic. | c %-----------------------------------------------% c do 80 j = 1,n do 70 i = itop, ibot cfac(i,j) = cmplx( ab(i,j)-sigmar*mb(i,j), & -sigmai*mb(i,j) ) 70 continue 80 continue c call cgbtrf(n, n, kl, ku, cfac, lda, iwork, ierr) if ( ierr .NE. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 90 continue c call snaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2 ) then c if (sigmai .eq. zero) then c c %----------------------------------% c | Shift is real. Perform | c | y <--- OP*x = inv[A-sigmar*I]*x | c | to force the starting vector | c | into the range of OP. | c %----------------------------------% c call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _bgtrs. ' print*, ' ' go to 9000 end if c else c c %--------------------------------------------% c | Shift is COMPLEX. Perform | c | y <--- OP*x = Real_Part{inv[A-sigma*I]*x} | c | to force the starting vector into the | c | range of OP. | c %--------------------------------------------% c do 100 j = 1, n workc(j) = cmplx(workd(ipntr(1)+j-1)) 100 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 110 j = 1, n workd(ipntr(2)+j-1) = real(workc(j)) 110 continue c end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | to force the starting vector into | c | the range of OP. | c %-----------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = Real_part{inv[A-SIGMA*M]*M}*x | c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c if ( sigmai .eq. zero ) then c c %---------------------% c | Shift is real, stay | c | in real arithmetic. | c %---------------------% c call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else c c %--------------------------% c | Goto complex arithmetic. | c %--------------------------% c do 120 i = 1,n workc(i) = cmplx(workd(ipntr(2)+i-1)) 120 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 130 i = 1, n workd(ipntr(2)+i-1) = real(workc(i)) 130 continue c end if c else if ( type .eq. 5) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*I]}*x | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c do 140 j = 1, n workc(j) = cmplx(workd(ipntr(1)+j-1)) 140 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 150 j = 1, n workd(ipntr(2)+j-1) = aimag(workc(j)) 150 continue c else if ( type .eq. 6 ) then c c %----------------------------------------% c | Perform y <-- OP*x | c | Imaginary_part{inv[A-SIGMA*M]*M} | c | to force the starting vector into the | c | range of OP. | c %----------------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c do 160 i = 1,n workc(i) = cmplx(workd(ipntr(2)+i-1)) 160 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 170 i = 1, n workd(ipntr(2)+i-1) = aimag(workc(i)) 170 continue c end if c else if (ido .eq. 1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2) then c if ( sigmai .eq. zero) then c c %----------------------------------% c | Shift is real. Perform | c | y <--- OP*x = inv[A-sigmar*I]*x. | c %----------------------------------% c call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) else c c %------------------------------------------% c | Shift is COMPLEX. Perform | c | y <-- OP*x = Real_Part{inv[A-sigma*I]*x} | c | in COMPLEX arithmetic. | c %------------------------------------------% c do 180 j = 1, n workc(j) = cmplx(workd(ipntr(1)+j-1)) 180 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 190 j = 1, n workd(ipntr(2)+j-1) = real(workc(j)) 190 continue c end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %--------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %--------------------------------------% c if ( sigmai .eq. zero ) then c c %------------------------% c | Shift is real, stay in | c | real arithmetic. | c %------------------------% c call scopy(n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else c c %---------------------------% c | Go to COMPLEX arithmetic. | c %---------------------------% c do 200 i = 1,n workc(i) = cmplx(workd(ipntr(3)+i-1)) 200 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error in _gbtrs.' print*, ' ' go to 9000 end if c do 210 i = 1,n workd(ipntr(2)+i-1) = real(workc(i)) 210 continue c end if c else if ( type .eq. 5 ) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*I]*x} | c %---------------------------------------% c do 220 j = 1, n workc(j) = cmplx(workd(ipntr(1)+j-1)) 220 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _NBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c do 230 j = 1, n workd(ipntr(2)+j-1) = aimag(workc(j)) 230 continue c else if ( type .eq. 6) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = Imaginary_part{inv[A-SIGMA*M]*M}*x. | c %-----------------------------------------% c do 240 i = 1,n workc(i) = cmplx(workd(ipntr(3)+i-1)) 240 continue c call cgbtrs ('Notranspose', n, kl, ku, 1, cfac, lda, & iwork, workc, n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_NBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c do 250 i = 1, n workd(ipntr(2)+i-1) = aimag(workc(i)) 250 continue c end if c else if (ido .eq. 2) then c c %--------------------% c | Perform y <-- M*x | c | Not used when | c | type = 1,2. | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else c c %-----------------------------------------% c | Either we have convergence, or there is | c | error. | c %-----------------------------------------% c if ( info .lt. 0) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd ' print *, ' ' go to 9000 c else c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c if (iparam(5) .gt. 0) then c call sneupd ( rvec, 'A', select, dr, di, z, ldz, & sigmar, sigmai, workev, bmat, n, which, & nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' go to 9000 c else if ( sigmai .ne. zero ) then c if ( type .eq. 4 .or. type .eq. 6 ) then c first = .true. do 270 j = 1, iparam(5) c c %----------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original | c | generalized eigenvalue problem. | c %----------------------------------% c if ( di(j) .eq. zero ) then c c %--------------------------------------% c | Eigenvalue is real. Compute | c | d = (x'*inv[A-sigma*M]*M*x) / (x'*x) | c %--------------------------------------% c call sgbmv('Nontranspose', n, n, kl, ku, one, $ mb(itop,1), lda, z(1,j), 1, zero, $ workd, 1) do i = 1, n workc(i) = cmplx(workd(i)) end do call cgbtrs ('Notranspose', n, kl, ku, 1, $ cfac, lda, iwork, workc, n, info) do i = 1, n workd(i) = real(workc(i)) workd(i+n) = aimag(workc(i)) end do denr = sdot(n, z(1,j), 1, workd, 1) deni = sdot(n, z(1,j), 1, workd(n+1), 1) numr = snrm2(n, z(1,j), 1)**2 dmdul = slapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar + numr*denr / dmdul else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 end if c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %-------------% c | Compute M*x | c %-------------% c call sgbmv('Nontranspose', n, n, kl, ku, $ one, mb(itop,1), lda, z(1,j), 1, zero, $ workd, 1) call sgbmv('Nontranspose', n, n, kl, ku, $ one, mb(itop,1), lda, z(1,j+1), 1, $ zero, workd(n+1), 1) do i = 1, n workc(i) = cmplx(workd(i),workd(i+n)) end do c c %----------------------------% c | Compute inv(A-sigma*M)*M*x | c %----------------------------% c call cgbtrs('Notranspose',n,kl,ku,1,cfac, $ lda, iwork, workc, n, info) c c %-------------------------------% c | Compute x'*inv(A-sigma*M)*M*x | c %-------------------------------% c do i = 1, n workd(i) = real(workc(i)) workd(i+n) = aimag(workc(i)) end do denr = sdot(n,z(1,j),1,workd,1) denr = denr+sdot(n,z(1,j+1),1,workd(n+1),1) deni = sdot(n,z(1,j),1,workd(n+1),1) deni = deni - sdot(n,z(1,j+1),1,workd,1) c c %----------------% c | Compute (x'*x) | c %----------------% c numr = slapy2( snrm2(n, z(1,j), 1), & snrm2(n, z(1, j+1), 1) )**2 c c %----------------------------------------% c | Compute (x'x) / (x'*inv(A-sigma*M)*Mx) | c %----------------------------------------% c dmdul = slapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar+numr*denr / dmdul di(j) = sigmai-numr*deni / dmdul first = .false. else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 c end if c else c c %---------------------------% c | Get the second eigenvalue | c | of the conjugate pair by | c | taking the conjugate of | c | previous one. | c %---------------------------% c dr(j) = dr(j-1) di(j) = -di(j-1) first = .true. c end if c 270 continue c else if ( type .eq. 2 .or. type .eq. 5) then c first = .true. do 280 j = 1, iparam(5) c c %----------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original | c | standard eigenvalue problem. | c %----------------------------------% c if ( di(j) .eq. zero ) then c c %-------------------------------------% c | Eigenvalue is real. Compute | c | d = (x'*inv[A-sigma*I]*x) / (x'*x). | c %-------------------------------------% c do i = 1, n workc(i) = cmplx(z(i,j)) end do call cgbtrs ('Notranspose', n, kl, ku, 1, $ cfac, lda, iwork, workc, n, info) do i = 1, n workd(i) = real(workc(i)) workd(i+n) = aimag(workc(i)) end do denr = sdot(n,z(1,j),1,workd,1) deni = sdot(n,z(1,j),1,workd(n+1),1) numr = snrm2(n, z(1,j), 1)**2 dmdul = slapy2(denr,deni)**2 if ( dmdul .ge. safmin ) then dr(j) = sigmar + numr*denr / dmdul else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 c end if c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c do i = 1, n workc(i) = cmplx( z(i,j), z(i,j+1) ) end do c c %---------------------------% c | Compute inv[A-sigma*I]*x. | c %---------------------------% c call cgbtrs('Notranspose',n,kl,ku,1,cfac, $ lda, iwork, workc, n, info) c c %-----------------------------% c | Compute x'*inv(A-sigma*I)*x | c %-----------------------------% c do i = 1, n workd(i) = real(workc(i)) workd(i+n) = aimag(workc(i)) end do denr = sdot(n,z(1,j),1,workd,1) denr = denr+sdot(n,z(1,j+1),1,workd(n+1),1) deni = sdot(n,z(1,j),1,workd(n+1),1) deni = deni - sdot(n,z(1,j+1),1,workd,1) c c %----------------% c | Compute (x'*x) | c %----------------% c numr = slapy2( snrm2(n, z(1,j), 1), & snrm2(n, z(1,j+1), 1))**2 c c %----------------------------------------% c | Compute (x'x) / (x'*inv(A-sigma*I)*x). | c %----------------------------------------% c dmdul = slapy2(denr,deni)**2 if (dmdul .ge. safmin) then dr(j) = sigmar+numr*denr / dmdul di(j) = sigmai-numr*deni / dmdul first = .false. else c c %---------------------% c | dmdul is too small. | c | Exit to avoid | c | overflow. | c %---------------------% c info = -15 go to 9000 end if c else c c %---------------------------% c | Get the second eigenvalue | c | of the conjugate pair by | c | taking the conjugate of | c | previous one. | c %---------------------------% c dr(j) = dr(j-1) di(j) = -di(j-1) first = .true. c end if c 280 continue c end if c end if c end if c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %----------------------------------------% c go to 90 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr1.f000066400000000000000000000273361260666001200166540ustar00rootroot00000000000000 program snbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call SNBAND to find eigenvalues LAMBDA such that c A*x = LAMBDA*x. c c ... Use mode 1 of SNAUPD. c c\BeginLib c c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr1.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h, h2, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details, see the documentation | c | in SNBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / real (nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = 1.0E+2 isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, sigmai, & workev, n, a, m, lda, rfac, cfac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, workd, & workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR1 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr2.f000066400000000000000000000277011260666001200166510ustar00rootroot00000000000000 program snbdr2 c c ... Construct matrices A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Define the shift SIGMA = (SIGMAR, SIGMAI). c c ... Call SNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*x. c c ... Use mode 3 of SNAUPD. c c\BeginLib c c\Routines called: c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr2.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c--------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isub, isup, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h2, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy, sgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to (SIGMAR,SIGMAI)) to be | c | approximated. Since the shift-invert moded is | c | used, WHICH is set to 'LM'. The user can modify | c | NX, NEV, NCV, SIGMAR, SIGMAI to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 1.0E+4 sigmai = 0.0E+0 c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SNAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in SNBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / real (nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0E+1 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isub,j+1) = -one/h2 + rho/two/h a(isup,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR2 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr3.f000066400000000000000000000276021260666001200166520ustar00rootroot00000000000000 program snbdr3 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A and M are derived from the finite element c discretization of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition, c ... Call SNBAND to find eigenvalues LAMBDA such that c A*x = LAMBDA*M*x. c c ... Eigenvalues with largest real parts are sought. c c ... Use mode 2 of SNAUPD. c c\BeginLib c c\Routines called: c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr3.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. The number IDO is used for | c | reverse communication and has to be set to 0 at | c | the beginning. Setting INFO=0 indicates that we | c | using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv info = 0 tol = zero ido = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SNAUPD is used | c | (IPARAM(7) = 2). All these options can be changed | c | by the user. For details, see the documentation | c | in SNBAND. | c %---------------------------------------------------% c mode = 2 maxitr = 300 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real (n+1) c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 2.0E+0 / h m(idiag,j) = 4.0E+0 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0E+1 do 50 j = 1, n a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h m(isub,j) = one*h 50 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband( rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, A, M, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR3 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr4.f000066400000000000000000000276441260666001200166610ustar00rootroot00000000000000 program snbdr4 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A and M are derived from the finite element c discretization of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition. c c ... Define the shift SIGMA = (SIGMAR, SIGMAI). c c ... Call SNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*M*x. c c ... Use mode 3 of SNAUPD. c c\BeginLib c c\Routines called: c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr4.F SID: 2.6 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two, six parameter (one = 1.0E+0, zero = 0.0E+0, & two = 2.0E+0, six = 6.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 1.0E+1 sigmai = 0.0E+0 c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv info = 0 tol = zero ido = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of snaupd is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in snaupd. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = n iparam(7) = 3 c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real(n+1) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 2.0E+0 / h m(idiag,j) = 4.0E+0 * h / six 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = 1.0E+1 do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h/six m(isub,j) = one*h/six 40 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, A, M, lda, rfac, cfac, kl, ku, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR4 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 50 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 50 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relatve residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr5.f000066400000000000000000000276361260666001200166630ustar00rootroot00000000000000 program snbdr5 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A is a block tridiagonal matrix. Each c diagonal block is a tridiagonal matrix with c 4 on the diagonal, 1-rho*h/2 on the subdiagonal and c 1+rho*h/2 on the superdiagonal. Each off-diagonal block c of A is an identity matrices. c c ... Define COMPLEX shift SIGMA = (SIGMAR,SIGMAI), SIGMAI .ne. 0. c c ... Call SNBAND to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*x. c c ... Use mode 4 of SNAUPD. c c\BeginLib c c\Routines called: c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr5.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the size of each block diagonal | c | of A. The number N(=NX*NX) is the dimension of | c | the matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to (SIGMAR,SIGMAI)) to be | c | approximated. Since the shift-invert moded is | c | used, WHICH is set to 'LM'. The user can modify | c | NX, NEV, NCV, SIGMAR, SIGMAI to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 4.0E-1 sigmai = 6.0E-1 c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of SNAUPD is used | c | (IPARAM(7) = 4). All these options can be changed | c | by the user. For details, see the documentation | c | in SNBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 m(idiag,j) = 4.0E+0 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+kl+2 h = one / real (nx+1) rho = 1.0E+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one+h*rho/two a(isub,j) = -one-h*rho/two 40 continue 50 continue c do 60 j = 1, n-1 m(isup,j+1) = one m(isub,j) = one 60 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one a(isub,j) = -one 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, ku, kl, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR5 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SNBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/snbdr6.f000066400000000000000000000314741260666001200166570ustar00rootroot00000000000000 program snbdr6 c c ... Construct matrices A and M in LAPACK-style band form. c The matrix A is a block tridiagonal matrix. Each c diagonal block is a tridiagonal matrix with c 4 on the diagonal, 1-rho*h/2 on the subdiagonal and c 1+rho*h/2 on the superdiagonal. Each subdiagonal block c of A is an identity matrix. The matrix M is the c tridiagonal matrix with 4 on the diagonal and 1 on the c subdiagonal and superdiagonal. c c ... Define COMPLEX shift SIGMA=(SIGMAR,SIGMAI), SIGMAI .ne. zero. c c ... Call snband to find eigenvalues LAMBDA closest to SIGMA c such that c A*x = LAMBDA*M*x. c c ... Use mode 4 of SNAUPD. c c\BeginLib c c\Routines called: c snband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr6.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c--------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & workev(3*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv, 3), ax(maxn), mx(maxn) Complex & cfac(lda, maxn), workc(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, idiag, isup, isub, mode, maxitr, & nconv logical rvec, first Real & tol, rho, h, sigmar, sigmai c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , & two = 2.0E+0 ) c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-----------------------------------------------------% c | The number NX is the size of each diagonal block of | c | A. The number N(=NX*NX) is the dimension of the | c | matrix. The number N(=NX*NX) is the dimension of | c | the matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV numbers of eigenvalues | c | closest to the COMPLEX shift (SIGMAR,SIGMAI) | c | (WHICH='LM') and their corresponding eigenvectors | c | are computed. The user can modify NX, NEV, NCV, | c | WHICH to solve problems of different sizes, and | c | to get different parts the spectrum. However, the | c | following rules must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0E-1 sigmai = 6.0E-1 c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of SNAUPD is used | c | (IPARAm(7) = 4). All these options can be changed | c | by the user. For details, see the documentation | c | in snband. | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 m(idiag,j) = 4.0E+0 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 h = one / real (nx+1) rho = 1.0E+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isub,j+1) = -one+h*rho/two a(isup,j) = -one-h*rho/two 40 continue 50 continue c do 60 j = 1, n-1 m(isub,j+1) = one m(isup,j) = one 60 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one a(isub,j) = -one 70 continue 80 continue c c %------------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. The real parts of the | c | eigenvalues are returned in the first column | c | of D, the imaginary parts are returned in the | c | second column of D. Eigenvectors are returned | c | in the first NCONV (=IPARAM(5)) columns of V. | c %------------------------------------------------% c rvec = .true. call snband(rvec, 'A', select, d, d(1,2), v, ldv, sigmar, & sigmai, workev, n, a, m, lda, rfac, cfac, ku, kl, & which, bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, workc, iwork, info) c if ( info .eq. 0) then c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c nconv = iparam(5) c print *, ' ' print *, ' _NBDR6 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c first = .true. do 90 j = 1, nconv c if ( d(j,2) .eq. zero ) then c c %--------------------% c | Ritz value is real | c %--------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if ( first ) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j+1), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j+1), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 90 continue call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for snband. | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssband.f000066400000000000000000000766761260666001200167500ustar00rootroot00000000000000c \BeginDoc c c \Name: ssband c c \Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal (Lanczos) basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style band form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are called Ritz values and Ritz vectors respectively. They are referred c to as such in the comments that follow. The computed orthonormal basis c for the invariant subspace corresponding to these Ritz values is referred c to as a Lanczos basis. c c ssband can be called with one of the following modes: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 in SSAUPD) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c The choice of mode must be specified in IPARAM(7) defined below. c c \Usage c call ssband c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, N, AB, MB, LDA, c RFAC, KL, KU, WHICH, BMAT, NEV, TOL, RESID, NCV, V, c LDV, IPARAM, WORKD, WORKL, LWORKL, IWORK, INFO ) c c \Arguments c c RVEC Logical (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the associated Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute all Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is not referenced. c c D Real array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by ssaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Lanczos basis array V computed by SSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Real (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Real array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Real array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array AB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7) = 1 c c LDA Integer. (INPUT) c Leading dimension of AB, MB, RFAC. c c RFAC Real array of LDA by N. (WORKSPACE/OUTPUT) c RFAC is used to store the LU factors of MB when IPARAM(7) = 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when IPARAM(7) = 3,4,5 is invoked. c It is not referenced when IPARAM(7) = 1. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When IPARAM(7)= 1 or 2, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LA' -> want the NEV eigenvalues of largest REAL part. c 'SA' -> want the NEV eigenvalues of smallest REAL part. c 'BE' -> Compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from c the high end than from the low end. c c When IPARAM(7) = 3, 4, or 5, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c Represents the dimension of the Lanczos basis constructed c by ssaupd for OP. c c V Real array N by NCV. (OUTPUT) c Upon INPUT: the NCV columns of V contain the Lanczos basis c vectors as constructed by ssaupd for OP. c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c represent the Ritz vectors that span the desired c invariant subspace. c NOTE: The array Z may be set equal to first NEV columns of the c Lanczos basis vector array V computed by ssaupd. In this case c if RVEC=.TRUE., the first NCONV=IPARAM(5) columns of V contain c the desired Ritz vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ------------------------------------------------------------ c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of ssband for the c five modes available. c c IPARAM(8) = NP c Not referenced. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c WORKD Real work array of length at least 3*n. (WORKSPACE) c c WORKL Real work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV. c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used when IPARAM(7)=2,3,4,5 to store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 in SSAUPD. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informational error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -13: HOWMNY must be one of 'A' or 'P' c = -14: SSAUPD did not find any eigenvalues to sufficient c accuracy. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current c Arnoldi factorization. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgbtrf LAPACK band matrix factorization routine. c sgbtrs LAPACK band linear system solve routine. c slacpy LAPACK matrix copy routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c--------------------------------------------------------------------- c subroutine ssband( rvec, howmny, select, d, z, ldz, sigma, & n, ab, mb, lda, rfac, kl, ku, which, bmat, nev, & tol, resid, ncv, v, ldv, iparam, workd, workl, & lworkl, iwork, info) c c %------------------% c | Scalar Arguments | c %------------------% c character which*2, bmat, howmny integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Real & tol, sigma logical rvec c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(*), iwork(*) logical select(*) Real & d(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), rfac(lda,*), & workd(*), workl(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, type, imid, itop, ibot, ierr c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Real & sdot, snrm2, slapy2 external sdot, scopy, sgbmv, sgbtrf, & sgbtrs, snrm2, slapy2, slacpy c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------------------% c | Set type of the problem to be solved. Check consistency | c | between BMAT and IPARAM(7). | c | type = 1 --> Solving standard problem in regular mode. | c | type = 2 --> Solving standard problem in shift-invert mode. | c | type = 3 --> Solving generalized problem in regular mode. | c | type = 4 --> Solving generalized problem in shift-invert mode. | c | type = 5 --> Solving generalized problem in Buckling mode. | c | type = 6 --> Solving generalized problem in Cayley mode. | c %----------------------------------------------------------------% c if ( iparam(7) .eq. 1 ) then type = 1 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'I') then type = 2 else if ( iparam(7) .eq. 2 ) then type = 3 else if ( iparam(7) .eq. 3 .and. bmat .eq. 'G') then type = 4 else if ( iparam(7) .eq. 4 ) then type = 5 else if ( iparam(7) .eq. 5 ) then type = 6 else print*, ' ' print*, 'BMAT is inconsistent with IPARAM(7).' print*, ' ' go to 9000 end if c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( type .eq. 2 .or. type .eq. 6 .and. bmat .eq. 'I' ) then c c %----------------------------------% c | Solving a standard eigenvalue | c | problem in shift-invert or | c | Cayley mode. Factor (A-sigma*I). | c %----------------------------------% c call slacpy ('A', ibot, n, ab, lda, rfac, lda ) do 10 j = 1, n rfac(imid,j) = ab(imid,j) - sigma 10 continue call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr ) if (ierr .ne. 0) then print*, ' ' print*, ' _SBAND: Error with _gbtrf. ' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %----------------------------------------------% c | Solving generalized eigenvalue problem in | c | regular mode. Copy M to rfac and Call LAPACK | c | routine sgbtrf to factor M. | c %----------------------------------------------% c call slacpy ('A', ibot, n, mb, lda, rfac, lda ) call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_SBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 .or. type .eq. 5 .or. type .eq. 6 & .and. bmat .eq. 'G' ) then c c %-------------------------------------------% c | Solving generalized eigenvalue problem in | c | shift-invert, Buckling, or Cayley mode. | c %-------------------------------------------% c c %-------------------------------------% c | Construct and factor (A - sigma*M). | c %-------------------------------------% c do 60 j = 1,n do 50 i = itop, ibot rfac(i,j) = ab(i,j) - sigma*mb(i,j) 50 continue 60 continue c call sgbtrf(n, n, kl, ku, rfac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_SBAND: Error with _gbtrf.' print*, ' ' go to 9000 end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 90 continue c call ssaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2 ) then c c %----------------------------------% c | Perform | c | y <--- OP*x = inv[A-sigma*I]*x | c | to force the starting vector | c | into the range of OP. | c %----------------------------------% c call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _bgtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | to force the starting vector into | c | the range of OP. | c %-----------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call scopy(n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with sbgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*M | c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 5) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*A | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call sgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 6 ) then c c %---------------------------------------% c | Perform y <-- OP*x | c | = (inv[A-SIGMA*M])*(A+SIGMA*M)*x | c | to force the starting vector into the | c | range of OP. | c %---------------------------------------% c if ( bmat .eq. 'G' ) then call sgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) call sgbmv('Notranspose', n, n, kl, ku, sigma, & mb(itop,1), lda, workd(ipntr(1)), 1, & one, workd(ipntr(2)), 1) else call scopy(n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, sigma, & workd(ipntr(2)), 1) end if c call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c end if c else if (ido .eq. 1) then c if ( type .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( type .eq. 2) then c c %----------------------------------% c | Perform | c | y <--- OP*x = inv[A-sigma*I]*x. | c %----------------------------------% c call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 3 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) call scopy(n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: error with _bgtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 4 ) then c c %-------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %-------------------------------------% c call scopy(n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgbtrs ('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_SBAND: Error with _gbtrs.' print*, ' ' go to 9000 end if c else if ( type .eq. 5 ) then c c %-------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*A*x | c | B*x = A*x has been computed | c | and saved in workd(ipntr(3)). | c %-------------------------------% c call scopy (n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' _SBAND: Error with _gbtrs. ' print*, ' ' go to 9000 end if c else if ( type .eq. 6) then c c %---------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*(A+SIGMA*M)*x. | c | (M*x) has been saved in | c | workd(ipntr(3)). | c %---------------------------------% c if ( bmat .eq. 'G' ) then call sgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) call saxpy( n, sigma, workd(ipntr(3)), 1, & workd(ipntr(2)), 1 ) else call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call sgbmv('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, sigma, & workd(ipntr(2)), 1) end if call sgbtrs('Notranspose', n, kl, ku, 1, rfac, lda, & iwork, workd(ipntr(2)), n, ierr) c end if c else if (ido .eq. 2) then c c %----------------------------------% c | Perform y <-- B*x | c | Note when Buckling mode is used, | c | B = A, otherwise B=M. | c %----------------------------------% c if (type .eq. 5) then c c %---------------------% c | Buckling Mode, B=A. | c %---------------------% c call sgbmv('Notranspose', n, n, kl, ku, one, & ab(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) else call sgbmv('Notranspose', n, n, kl, ku, one, & mb(itop,1), lda, workd(ipntr(1)), 1, & zero, workd(ipntr(2)), 1) end if c else c c %-----------------------------------------% c | Either we have convergence, or there is | c | error. | c %-----------------------------------------% c if ( info .lt. 0) then c c %--------------------------% c | Error message, check the | c | documentation in SSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' go to 9000 c else c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c if (iparam(5) .gt. 0) then c call sseupd ( rvec, 'A', select, d, z, ldz, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of sneupd. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' go to 9000 c end if c end if c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %----------------------------------------% c go to 90 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr1.f000066400000000000000000000241031260666001200166460ustar00rootroot00000000000000 program ssbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition using standard c central difference. c c ... Call SSBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 1 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr1.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv Real & tol, sigma, h2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian operator on the unit square with zero | c | Dirichlet boundary condition. The number | c | N(=NX*NX) is the dimension of the matrix. A | c | standard eigenvalue problem is solved | c | (BMAT = 'I'). NEV is the number of eigenvalues | c | to be approximated. The user can modify NX,NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | SSBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h2 = one / ((nx+1)*(nx+1)) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one / h2 a(isub,j) = -one / h2 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR1 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr2.f000066400000000000000000000241751260666001200166600ustar00rootroot00000000000000 program ssbdr2 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-dimensional Laplacian on the unit square c with zero Dirichlet boundary condition using standard c central difference. c c ... Call SSBAND to find eigenvalues LAMBDA closest to c SIGMA such that c A*x = x*LAMBDA. c c ... Use mode 3 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr2.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(3*maxncv*maxncv+6*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, i, j, ido, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv Real & tol, sigma, h2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy, sgbmv c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian operator on the unit square with zero | c | Dirichlet boundary condition. The number | c | N(=NX*NX) is the dimension of the matrix. A | c | standard eigenvalue problem is solved | c | (BMAT = 'I'). NEV is the number of eigenvalues | c | (closest to the shift SIGMA) to be approximated. | c | Since the shift and invert mode is used, WHICH | c | is set to 'LM'. The user can modify NX, NEV, | c | NCV and SIGMA to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SSAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details see the documentation in | c | SSBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h2 = one / ((nx+1)*(nx+1)) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = 4.0E+0 / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one / h2 a(isub,j) = -one / h2 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec,'A', select, d, v, ldv, sigma, n, a, m, & lda, rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR2 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr3.f000066400000000000000000000232251260666001200166540ustar00rootroot00000000000000 program ssbdr3 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call SSBAND with regular mode to find eigenvalues LAMBDA c such that c A*x = LAMBDA*M*x. c c ... Use mode 2 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr3.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Real & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two, four, six parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 , & four = 4.0E+0 , six = 6.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy, sgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. The user can modify N, NEV, | c | NCV and WHICH to solve problems of different | c | sizes, and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SSAUPD is used | c | (IPARAM(7) = 2). All these options can be changed | c | by the user. For details see the documentation in | c | SSBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 2 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR3 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr4.f000066400000000000000000000233141260666001200166540ustar00rootroot00000000000000 program ssbdr4 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call SSBAND with shift-invert mode to find eigenvalues LAMBDA c closest to SIGMA such that c A*x = LAMBDA*M*x. c c ... Use mode 3 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr4.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Real & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two, four, six parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 , & four = 4.0E+0 , six = 6.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy, sgbmv c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | (closest to the shift SIGMA) to be approximated. | c | Since the shift and invert mode is used, WHICH | c | is set to 'LM'. The user can modify N, NEV, NCV | c | and SIGMA to solve problems of different sizes, | c | and to get different parts the spectrum. | c | However, the following conditions must be | c | satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SSAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in SSBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec, 'A', select, d, v, ldv, sigma, n, a, m, & lda, rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR4 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr5.f000066400000000000000000000233631260666001200166610ustar00rootroot00000000000000 program ssbdr5 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, KG is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call SSBAND with Buckling mode to find eigenvalues LAMBDA c such that c A*x = M*x*LAMBDA. c c ... Use mode 4 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr5.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Real & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two, four, six parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 , & four = 4.0E+0 , six = 6.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, sgbmv, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. Since the Buckling mode is | c | is used, WHICH is set to 'LM'. The user can | c | modify N, NEV, NCV and SIGMA to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 1.0 c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 of SSAUPD is used | c | (IPARAM(7) = 4). All these options can be changed | c | by the user. For details see the documentation in | c | SSBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 4 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR5 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _sband, info= ', info print *, ' Check the documentation of _sband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/ssbdr6.f000066400000000000000000000233441260666001200166610ustar00rootroot00000000000000 program ssbdr6 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is the 1-dimensional discrete Laplacian on [0,1] c with zero Dirichlet boundary condition, M is the mass c formed by using piecewise linear elements on [0,1]. c c ... Call SSBAND with Cayley mode to find eigenvalues LAMBDA such that c A*x = LAMBDA*M*x. c c ... Use mode 5 of SSAUPD. c c\BeginLib c c\Routines called: c ssband ARPACK banded eigenproblem solver. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK routine to initialize a matrix to zero. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c sgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sbdr6.F SID: 2.5 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Real & a(lda,maxn), m(lda,maxn), rfac(lda,maxn), & workl(maxncv*maxncv+8*maxncv), workd(3*maxn), & v(ldv, maxncv), resid(maxn), d(maxncv, 2), & ax(maxn), mx(maxn) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, ido, & n, isub, isup, idiag, maxitr, mode, nconv Real & tol, h, sigma, r1, r2 logical rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two, four, six parameter (one = 1.0E+0 , zero = 0.0E+0 , two = 2.0E+0 , & four = 4.0E+0 , six = 6.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy, sgbmv c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved | c | (BMAT = 'G'). NEV is the number of eigenvalues | c | to be approximated. Since the Cayley mode is | c | used, WHICH is set to 'LM'. The user can | c | modify N, NEV, NCV and SIGMA to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SBDR6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SBDR6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SBDR6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 150.0 c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv**2+8*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 5 of SSAUPD is used | c | (IPARAM(7) = 5). All these options can be changed | c | by the user. For details, see the documentation | c | in SBAND. | c %---------------------------------------------------% c maxitr = 300 mode = 5 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call slaset('A', lda, n, zero, zero, a, lda) call slaset('A', lda, n, zero, zero, m, lda) call slaset('A', lda, n, zero, zero, rfac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / real (n+1) r1 = four / six idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = r1 * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c r2 = one / six isup = kl+ku isub = kl+ku+2 do 60 j = 1, n-1 a(isup,j+1) = -one / h a(isub,j) = -one / h m(isup,j+1) = r2 * h m(isub,j) = r2 * h 60 continue c c %-------------------------------------% c | Call SSBAND to find eigenvalues and | c | eigenvectors. Eigenvalues are | c | returned in the first column of D. | c | Eigenvectors are returned in the | c | first NCONV (=IPARAM(5)) columns of | c | V. | c %-------------------------------------% c rvec = .true. call ssband( rvec, 'A', select, d, v, ldv, sigma, n, a, m, lda, & rfac, kl, ku, which, bmat, nev, tol, & resid, ncv, v, ldv, iparam, workd, workl, lworkl, & iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, ' _SBDR6 ' print *, ' ====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Lanczos vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv call sgbmv('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call sgbmv('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 90 continue call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for SSBAND. | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/znband.f000066400000000000000000000553141260666001200167340ustar00rootroot00000000000000c \BeginDoc c c \Name: znband c c \Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c Matrices A and B are stored in LAPACK-style banded form. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Schur basis. c c znband can be called with one of the following modes: c c Mode 1: A*z = lambda*z. c ===> OP = A and B = I. c c Mode 2: A*z = lambda*M*z, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c c Mode 3: A*z = lambda*M*z, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode. c c Choice of different modes can be specified in IPARAM(7) defined below. c c \Usage c call znband c ( RVEC, HOWMNY, SELECT, D , Z, LDZ, SIGMA, WORKEV, N, AB, c MB, LDA, FAC, KL, KU, WHICH, BMAT, NEV, TOL, RESID, NCV, c V, LDV, IPARAM, WORKD, WORKL, LWORKL, RWORK, IWORK, INFO ) c c \Arguments c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the invariant subspace to be computed c corresponding to the converged Ritz values. c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the real Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex*16 array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex*16 N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV columns of the c array V. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex*16 (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex*16 work array of dimension NCV. (WORKSPACE) c c N Integer. (INPUT) c Dimension of the eigenproblem. c c AB Complex*16 array of dimension LDA by N. (INPUT) c The matrix A in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of A is stored in the j-th column of the c array AB as follows: c AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c c MB Complex*16 array of dimension LDA by N. (INPUT) c The matrix M in band storage, in rows KL+1 to c 2*KL+KU+1; rows 1 to KL of the array need not be set. c The j-th column of M is stored in the j-th column of the c array MB as follows: c MB(kl+ku+1+i-j,j) = M(i,j) for max(1,j-ku)<=i<=min(m,j+kl) c Not referenced if IPARAM(7)=1. c c LDA Integer. (INPUT) c Leading dimension of AB, MB, FAC. c c FAC Complex*16 array of LDA by N. (WORKSPACE/OUTPUT) c FAC is used to store the LU factors of MB when mode 2 c is invoked. It is used to store the LU factors of c (A-sigma*M) when mode 3 is invoked. c It is not referenced when IPARAM(7)=1. c c KL Integer. (INPUT) c Max(number of subdiagonals of A, number of subdiagonals of M) c c KU Integer. (OUTPUT) c Max(number of superdiagonals of A, number of superdiagonals of M) c c WHICH Character*2. (INPUT) c When mode 1,2 are used, WHICH can be set to any one of c the following. c c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c When mode 3 is used, WHICH should be set to 'LM' only. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c NEV Integer. (INPUT) c Number of eigenvalues of to be computed. c c TOL Double precision scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = dlamch ('EPS') (machine precision as computed c by the LAPACK auxilliary subroutine dlamch ). c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c c V Complex*16 array N by NCV. (OUTPUT) c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then c the first NCONV=IPARAM(5) columns of V will contain Ritz vectors c of the eigensystem A*z = lambda*B*z. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. LDV must be great than or equal to N. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c It is set to 1 in this subroutine. The user do not need c to set this parameter. c ---------------------------------------------------------- c ISHIFT = 1: exact shift with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ------------------------------------------------------------- c c IPARAM(2) = Not referenced. c c IPARAM(3) = MXITER c On INPUT: max number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" eigenvalues. c c IPARAM(6) = IUPD c Not referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2 or 3; See under \Description of znband for the c three modes available. c c WORKD Complex*16 work array of length at least 3*n. (WORKSPACE) c c WORKL Complex*16 work array of length LWORKL. (WORKSPACE) c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Double precision array of length N (WORKSPACE) c Workspace used in znaupd . c c IWORK Integer array of dimension at least N. (WORKSPACE) c Used to mode 2,3. Store the pivot information in the c factorization of M or (A-SIGMA*M). c c INFO Integer. (INPUT/OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: ZNAUPD did not find any eigenvalues to sufficient c accuracy. c c \EndDoc c c------------------------------------------------------------------------ c c\BeginLib c c\Routines called c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgbtrf LAPACK band matrix factorization routine. c zgbtrs LAPACK band linear system solve routine. c zlacpy LAPACK matrix copy routine. c zcopy Level 1 BLAS that copies one vector to another. c dznrm2 Level 1 BLAS that computes the norm of a vector. c zgbmv Level 2 BLAS that computes the band matrix vector product. c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Ph.D thesis, TR95-13, Rice Univ, c May 1995. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nband.F SID: 2.3 DATE OF SID: 10/17/00 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine znband (rvec, howmny, select, d , z, ldz, sigma, & workev, n, ab, mb, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info ) c c %------------------% c | Scalar Arguments | c %------------------% c Character which*2, bmat, howmny Logical rvec Integer n, lda, kl, ku, nev, ncv, ldv, & ldz, lworkl, info Complex*16 & sigma Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c Integer iparam(*), iwork(*) Logical select(*) Complex*16 & d(*), resid(*), v(ldv,*), z(ldz,*), & ab(lda,*), mb(lda,*), fac(lda,*), & workd(*), workl(*), workev(*) Double precision & rwork(*) c c %--------------% c | Local Arrays | c %--------------% c integer ipntr(14) c c %---------------% c | Local Scalars | c %---------------% c integer ido, i, j, mode, ierr, itop, imid, ibot c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) ) c c %-----------------------------% c | LAPACK & BLAS routines used | c %-----------------------------% c Double precision & dznrm2 external zcopy , zgbmv , zgbtrf , zgbtrs , dznrm2 , zlacpy c c %-----------------------% c | Executable Statements | c %-----------------------% c mode = iparam(7) c c %------------------------% c | Initialize the reverse | c | communication flag. | c %------------------------% c ido = 0 c c %----------------% c | Exact shift is | c | used. | c %----------------% c iparam(1) = 1 c c %-----------------------------------% c | Both matrices A and M are stored | c | between rows itop and ibot. Imid | c | is the index of the row that | c | stores the diagonal elements. | c %-----------------------------------% c itop = kl + 1 imid = kl + ku + 1 ibot = 2*kl + ku + 1 c if ( mode .eq. 2 ) then c c %-----------------------------------------------% c | Copy M to fac and Call LAPACK routine zgbtrf | c | to factor M. | c %-----------------------------------------------% c call zlacpy ('A', ibot, n, mb, lda, fac, lda ) call zgbtrf (n, n, kl, ku, fac, lda, iwork, ierr) if (ierr .ne. 0) then print*, ' ' print*,'_band: error in _gbtrf' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c if (bmat .eq. 'I') then c c %-------------------------% c | Construct (A - sigma*I) | c %-------------------------% c call zlacpy ('A', ibot, n, ab, lda, fac, lda ) do 10 j = 1,n fac(imid,j) = ab(imid,j) - sigma 10 continue c else c c %---------------------------% c | Construct (A - sigma*M) | c %---------------------------% c do 30 j = 1,n do 20 i = itop, ibot fac(i,j) = ab(i,j) - sigma*mb(i,j) 20 continue 30 continue c end if c c %------------------------% c | Factor (A - sigma*M) | c %------------------------% c call zgbtrf (n, n, kl, ku, fac, lda, iwork, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, '_band: error in _gbtrf.' print*, ' ' go to 9000 end if c end if c c %--------------------------------------------% c | M A I N L O O P (reverse communication) | c %--------------------------------------------% c 40 continue c call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1) then c if ( mode .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( mode .eq. 2 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call zgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in sbgtrs.' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c c %-----------------------------------------% c | Perform y <-- OP*x | c | = inv[A-SIGMA*M]*M* x c | to force the starting vector into the | c | range of OP. | c %-----------------------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call zgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c end if c else if (ido .eq. 1) then c if ( mode .eq. 1) then c c %----------------------------% c | Perform y <--- OP*x = A*x | c %----------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else if ( mode .eq. 2 ) then c c %-----------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c %-----------------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, ab(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c call zgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), ldv, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in sbgtrs.' print*, ' ' go to 9000 end if c else if ( mode .eq. 3 ) then c if ( bmat .eq. 'I' ) then c c %----------------------------------% c | Perform y <-- inv(A-sigma*I)*x. | c %----------------------------------% c call zcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) call zgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c else c c %--------------------------------------% c | Perform y <-- inv(A-sigma*M)*(M*x). | c | (M*x) has been computed and stored | c | in workd(ipntr(3)). | c %--------------------------------------% c call zcopy (n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call zgbtrs ('Notranspose', n, kl, ku, 1, fac, lda, & iwork, workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print*, ' ' print*, '_band: error in _gbtrs.' print*, ' ' go to 9000 end if c end if c endif c else if (ido .eq. 2) then c c %--------------------% c | Perform y <-- M*x | c %--------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, mb(itop,1), & lda, workd(ipntr(1)), 1, zero, & workd(ipntr(2)), 1) c else c c %-------------------------------------------% c | Either we have convergence, or there is | c | error. | c %-------------------------------------------% c if ( info .ne. 0) then c c %--------------------------% c | Error message, check the | c | documentation in dnaupd | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd ' print *, ' ' c else c call zneupd (rvec, howmny , select, d, z, ldz, sigma, & workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, rwork, info) c if ( info .ne. 0) then c c %------------------------------------% c | Check the documentation of zneupd . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', info print *, ' Check the documentation of _neupd ' print *, ' ' c endif c end if c go to 9000 c end if c c %----------------------------------------% c | L O O P B A C K to call znaupd again. | c %----------------------------------------% c go to 40 c 9000 continue c end arpack-ng-3.3.0/EXAMPLES/BAND/znbdr1.f000066400000000000000000000251011260666001200166470ustar00rootroot00000000000000 program znbdr1 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call ZNBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 1 of ZNAUPD . c c\BeginLib c c znband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zlaset LAPACK routine to initialize a matrix to zero. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c dznrm2 Level 1 BLAS that computes the norm of a vector. c zgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr1.F SID: 2.3 DATE OF SID: 08/26/96 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex*16 & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, i, j, & n, nx, lo, isub, isup, idiag, maxitr, mode, & nconv logical rvec Double precision & tol Complex*16 & rho, h, h2, sigma c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two parameter ( one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zgbmv , zaxpy , dlapy2 , zlaset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV and WHICH to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, the following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %-----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. Setting INFO=0 indicates that a | c | random vector is generated in ZNAUPD to start the | c | Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of ZNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details, see the documentation | c | in znband . | c %---------------------------------------------------% c maxitr = 300 mode = 1 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call zlaset ('A', lda, n, zero, zero, a, lda) call zlaset ('A', lda, n, zero, zero, m, lda) call zlaset ('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nx ku = nx c c %---------------% c | Main diagonal | c %---------------% c h = one / dcmplx (nx+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (4.0D+0, 0.0D+0) / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = (1.0D+2, 0.0D+0) isup = kl+ku isub = kl+ku+2 do 50 i = 1, nx lo = (i-1)*nx do 40 j = lo+1, lo+nx-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nx-1 lo = (i-1)*nx do 70 j = lo+1, lo+nx a(isup,nx+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call znband (rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR1 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv c c %---------------------------% c | Compute the residual norm | c | || A*x - lambda*x || | c %---------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call zaxpy (n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 90 continue call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for znband . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/znbdr2.f000066400000000000000000000253231260666001200166560ustar00rootroot00000000000000 program znbdr2 c c ... Construct the matrix A in LAPACK-style band form. c The matrix A is derived from the discretization of c the 2-d convection-diffusion operator c c -Laplacian(u) + rho*partial(u)/partial(x). c c on the unit square with zero Dirichlet boundary condition c using standard central difference. c c ... Call ZNBAND to find eigenvalues LAMBDA such that c A*x = x*LAMBDA. c c ... Use mode 3 of ZNAUPD . c c\BeginLib c c znband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zlaset LAPACK routine to initialize a matrix to zero. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c dznrm2 Level 1 BLAS that computes the norm of a vector. c zgbmv Level 2 BLAS that computes the band matrix vector product c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr2.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c---------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex*16 & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, kl, ku, info, i, j, & n, nxi, lo, isub, isup, idiag, maxitr, mode, & nconv logical rvec Double precision & tol Complex*16 & rho, h, h2, sigma c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zgbmv , zaxpy , dlapy2 , zlaset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues (closest to SIGMA) to be | c | approximated. Since the shift and invert mode | c | is used, WHICH is set to 'LM'. The user can | c | modify NX, NEV and NCV to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c nxi = 10 n = nxi*nxi nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. Setting INFO=0 indicates that a | c | random vector is generated in ZNAUPD to start the | c | Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 info = 0 c c %---------------------------------------------------% c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of ZNAUPD is used | c | (IPARAM(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in znband . | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %----------------------------------------% c | Construct the matrix A in LAPACK-style | c | banded form. | c %----------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call zlaset ('A', lda, n, zero, zero, a, lda) call zlaset ('A', lda, n, zero, zero, m, lda) call zlaset ('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = nxi ku = nxi c c %---------------% c | Main diagonal | c %---------------% c h = one / dcmplx (nxi+1) h2 = h*h c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (4.0D+0, 0.0D+0) / h2 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c rho = (1.0D+2, 0.0D+0) isup = kl+ku isub = kl+ku+2 do 50 i = 1, nxi lo = (i-1)*nxi do 40 j = lo+1, lo+nxi-1 a(isup,j+1) = -one/h2 + rho/two/h a(isub,j) = -one/h2 - rho/two/h 40 continue 50 continue c c %------------------------------------% c | KL-th subdiagonal and KU-th super- | c | diagonal. | c %------------------------------------% c isup = kl+1 isub = 2*kl+ku+1 do 80 i = 1, nxi-1 lo = (i-1)*nxi do 70 j = lo+1, lo+nxi a(isup,nxi+j) = -one / h2 a(isub,j) = -one / h2 70 continue 80 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call znband (rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR2 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c do 90 j = 1, nconv c c %---------------------------% c | Compute the residual norm | c | || A*x - lambda*x || | c %---------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call zaxpy (n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 90 continue call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for znband . | c %-------------------------------------% c print *, ' ' print *, ' Error with _nband, info= ', info print *, ' Check the documentation of _nband ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/znbdr3.f000066400000000000000000000244111260666001200166540ustar00rootroot00000000000000 program znbdr3 c c ... Construct matrices A and M in LAPACK-style band form. c Matrices A and M are derived from the finite c element discretization of the 1-dimensional c convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... Call ZNBAND to find eigenvalues LAMBDA such that c A*x = M*x*LAMBDA. c c ... Eigenvalues with largest real parts are sought. c c ... Use mode 2 of ZNAUPD . c c\BeginLib c c\Routines called: c znband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zlaset LAPACK routine to initialize a matrix to zero. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c dznrm2 Level 1 BLAS that computes the norm of a vector. c zgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr3.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex*16 & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn), mx(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, & n, idiag, isup, isub, maxitr, & mode, nconv logical rvec Double precision & tol Complex*16 & rho, h, sigma c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zgbmv , zaxpy , dlapy2 , zlaset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV and WHICH to solve problems | c | of different sizes, and to get different parts | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. Setting INFO=0 indicates that | c | using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv info = 0 tol = 0.0 c c %---------------------------------------------------% c | IPARAm(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of ZNAUPD is used | c | (IPARAm(7) = 2). All these options can be changed | c | by the user. For details, see the documentation | c | in znband . | c %---------------------------------------------------% c maxitr = 300 mode = 2 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call zlaset ('A', lda, n, zero, zero, a, lda) call zlaset ('A', lda, n, zero, zero, m, lda) call zlaset ('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dcmplx (n+1) c idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = (2.0D+0, 0.0D+0) / h m(idiag,j) = (4.0D+0, 0.0D+0) * h 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = (1.0D+1, 0.0D+0) do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h m(isub,j) = one*h 40 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call znband (rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR3 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c do 50 j = 1, nconv c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call zgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call zaxpy (n, -d(j), mx, 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1), rd(j,2)) 50 continue call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for znband . | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/BAND/znbdr4.f000066400000000000000000000246271260666001200166660ustar00rootroot00000000000000 program zndrv4 c c ... Construct matrices A and M in LAPACK-style band form. c Matries A and M are derived from the finite c element discretization of the 1-dimensional c convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... Call ZNBAND to find eigenvalues LAMBDA such that c A*x = M*x*LAMBDA. c c ... Use mode 3 of ZNAUPD . c c\BeginLib c c\Routines called: c znband ARPACK banded eigenproblem solver. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zlaset LAPACK routine to initialize a matrix to zero. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c dznrm2 Level 1 BLAS that computes the norm of a vector. c zgbmv Level 2 BLAS that computes the band matrix vector product. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nbdr4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c------------------------------------------------------------------------- c c %-------------------------------------% c | Define leading dimensions for all | c | arrays. | c | MAXN - Maximum size of the matrix | c | MAXNEV - Maximum number of | c | eigenvalues to be computed | c | MAXNCV - Maximum number of Arnoldi | c | vectors stored | c | MAXBDW - Maximum bandwidth | c %-------------------------------------% c integer maxn, maxnev, maxncv, maxbdw, lda, & lworkl, ldv parameter ( maxn = 1000, maxnev = 25, maxncv=50, & maxbdw=50, lda = maxbdw, ldv = maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), iwork(maxn) logical select(maxncv) Complex*16 & a(lda,maxn), m(lda,maxn), fac(lda,maxn), & workl(3*maxncv*maxncv+5*maxncv), workd(3*maxn), & workev(2*maxncv), v(ldv, maxncv), & resid(maxn), d(maxncv), ax(maxn), mx(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character which*2, bmat integer nev, ncv, ku, kl, info, j, & n, idiag, isup, isub, maxitr, mode, & nconv logical rvec Double precision & tol Complex*16 & rho, h, sigma c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two, four, six parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) , & four = (4.0D+0, 0.0D+0) , & six = (6.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zgbmv , zaxpy , dlapy2 , zlaset c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A generalized eigenvalue problem is | c | solved (BMAT = 'G'). NEV is the number of | c | eigenvalues (closest to the shift SIGMA) to be | c | approximated. Since the shift and invert mode | c | is used, WHICH is set to 'LM'. The user can | c | modify NX, NEV and NCV to solve problems of | c | different sizes, and to get different parts the | c | spectrum. However, the following conditions | c | must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %-------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NBDR4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NBDR4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NBDR4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = (1.0D+1, 0.0D+0) c c %----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL has to be set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine machine | c | precision is used. Setting INFO=0 indicates that | c | we using a randomly generated vector to start the | c | the ARNOLDI process. | c %----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv info = 0 tol = 0.0 c c %---------------------------------------------------% c | IPARAm(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of ZNAUPD is used | c | (IPARAm(7) = 3). All these options can be changed | c | by the user. For details, see the documentation | c | in znband . | c %---------------------------------------------------% c maxitr = 300 mode = 3 c iparam(3) = maxitr iparam(7) = mode c c %--------------------------------------------% c | Construct matrices A and M in LAPACK-style | c | banded form. | c %--------------------------------------------% c c %---------------------------------------------% c | Zero out the workspace for banded matrices. | c %---------------------------------------------% c call zlaset ('A', lda, n, zero, zero, a, lda) call zlaset ('A', lda, n, zero, zero, m, lda) call zlaset ('A', lda, n, zero, zero, fac, lda) c c %-------------------------------------% c | KU, KL are number of superdiagonals | c | and subdiagonals within the band of | c | matrices A and M. | c %-------------------------------------% c kl = 1 ku = 1 c c %---------------% c | Main diagonal | c %---------------% c h = one / dcmplx (n+1) idiag = kl+ku+1 do 30 j = 1, n a(idiag,j) = two / h m(idiag,j) = four * h / six 30 continue c c %-------------------------------------% c | First subdiagonal and superdiagonal | c %-------------------------------------% c isup = kl+ku isub = kl+ku+2 rho = (1.0D+1, 0.0D+0) do 40 j = 1, n-1 a(isup,j+1) = -one/h + rho/two a(isub,j) = -one/h - rho/two m(isup,j+1) = one*h / six m(isub,j) = one*h / six 40 continue c c %-----------------------------------------------% c | Call ARPACK banded solver to find eigenvalues | c | and eigenvectors. Eigenvalues are returned in | c | the one dimensional array D. Eigenvectors | c | are returned in the first NCONV (=IPARAM(5)) | c | columns of V. | c %-----------------------------------------------% c rvec = .true. call znband (rvec, 'A', select, d, v, ldv, sigma, & workev, n, a, m, lda, fac, kl, ku, which, & bmat, nev, tol, resid, ncv, v, ldv, iparam, & workd, workl, lworkl, rwork, iwork, info) c if ( info .eq. 0) then c nconv = iparam(5) c c %-----------------------------------% c | Print out convergence information | c %-----------------------------------% c print *, ' ' print *, '_NBDR4 ' print *, '====== ' print *, ' ' print *, ' The size of the matrix is ', n print *, ' Number of eigenvalue requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' The number of converged Ritz values is ', & nconv print *, ' What portion of the spectrum ', which print *, ' The number of Implicit Arnoldi ', & ' update taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence tolerance is ', tol print *, ' ' c do 90 j = 1, nconv c c %----------------------------% c | Compute the residual norm. | c | || A*x - lambda*x || | c %----------------------------% c call zgbmv ('Notranspose', n, n, kl, ku, one, & a(kl+1,1), lda, v(1,j), 1, zero, & ax, 1) call zgbmv ('Notranspose', n, n, kl, ku, one, & m(kl+1,1), lda, v(1,j), 1, zero, & mx, 1) call zaxpy (n, -d(j), mx, 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1), rd(j,2)) 90 continue call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') else c c %-------------------------------------% c | Either convergence failed, or there | c | is error. Check the documentation | c | for znband . | c %-------------------------------------% c print *, ' ' print *, ' Error with _band, info= ', info print *, ' Check the documentation of _band ' print *, ' ' c end if c 9000 end arpack-ng-3.3.0/EXAMPLES/COMPLEX/000077500000000000000000000000001260666001200157045ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/COMPLEX/Makefile.am000066400000000000000000000010221260666001200177330ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) CNDRV = cndrv1 cndrv2 cndrv3 cndrv4 ZNDRV = zndrv1 zndrv2 zndrv3 zndrv4 COMPLEX = $(CNDRV) $(ZNDRV) check_PROGRAMS = $(COMPLEX) TESTS = $(check_PROGRAMS) EXTRA_DIST = README # Complex problem using single complex cndrv1_SOURCES = cndrv1.f cndrv2_SOURCES = cndrv2.f cndrv3_SOURCES = cndrv3.f cndrv4_SOURCES = cndrv4.f # Complex problem using double complex zndrv1_SOURCES = zndrv1.f zndrv2_SOURCES = zndrv2.f zndrv3_SOURCES = zndrv3.f zndrv4_SOURCES = zndrv4.f arpack-ng-3.3.0/EXAMPLES/COMPLEX/README000066400000000000000000000027121260666001200165660ustar00rootroot000000000000001. Purpose ------- This directory contains example drivers that call ARPACK subroutines [c,z]naupd.f and [c,z]neupd.f to solve COMPLEX eigenvalue problems using regular, inverse or shift-invert modes. These drivers illustrate how to set various ARPACK parameters to solve different problems in different modes. They provide a guideline on how to use ARPACK's reverse communication interface. The user may modify any one of these drivers, and provide his/her own matrix vector multiplication routine to solve the problem of his/her own interest. 2. Naming convention ----------------- The name for each driver has the form 'XndrvN.f', where X - is 'c' (single precision complex) or 'z' (double precision complex) N - is a number between 1 and 4. If N = 1, the driver solves a STANDARD eigenvalue problem in REGULAR mode N = 2, the driver solves a STANDARD eigenvalue problem in SHIFT-INVERT mode. N = 3, the driver solves a GENERALIZED eigenvalue problem in INVERSE mode N = 4, the driver solves a GENERALIZED eigenvalue problem in SHIFT-INVERT mode. For shift-invert modes (N=2,4), the user needs to provide a complex linear system solver to perform y=inv[A-sigma*B]*x. 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make cndrv1". Then execute using "cndrv1". arpack-ng-3.3.0/EXAMPLES/COMPLEX/cndrv1.f000066400000000000000000000350551260666001200172600ustar00rootroot00000000000000 program cndrv1 c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit squre [0,1]x[0,1] with zero Dirichlet boundary c condition. c c ... OP = A and B = I. c c ... Assume "call av (nx,x,y)" computes y = A*x c c ... Use mode 1 of CNAUPD. c c\BeginLib c c\Routines called c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv1.F SID: 2.4 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Real & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex & sigma Real & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, caxpy, slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of CNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in CNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call cneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call caxpy(n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program cndrv1. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c subroutine av (nx, v, w) integer nx, j, lo Complex & v(nx*nx), w(nx*nx), one, h2 parameter (one = (1.0E+0, 0.0E+0) ) external caxpy, tv c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / cmplx((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call caxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call caxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex & x(nx), y(nx), h, h2, dd, dl, du c Complex & one, rho parameter (one = (1.0E+0, 0.0E+0) , & rho = (1.0E+2, 0.0E+0) ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / cmplx(nx+1) h2 = h*h dd = (4.0E+0, 0.0E+0) / h2 dl = -one/h2 - (5.0E-1, 0.0E+0) *rho/h du = -one/h2 + (5.0E-1, 0.0E+0) *rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/cndrv2.f000066400000000000000000000350511260666001200172550ustar00rootroot00000000000000 program cndrv2 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a standard complex nonsymmetric eigenvalue c problem. c c We implement example two of ex-complex.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the central difference discretization c of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition. c ... The shift sigma is a complex number. c c ... OP = inv[A-sigma*I] and B = I. c c ... Use mode 3 of CNAUPD. c c\BeginLib c c\Routines called: c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgttrf LAPACK tridiagonal factorization routine. c cgttrs LAPACK tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c ccopy Level 1 BLAS that copies one vector to another. c scnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv2.F SID: 2.6 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex & ax(maxn), d(maxncv), resid(maxn), & v(ldv, maxncv), workd(3*maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode Complex & h, h2, s, sigma, s1, s2, s3, rho common /convct/ rho c Real & tol logical rvec c c %------------% c | Parameters | c %------------% c Complex & one, zero, two parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external cgttrf, cgttrs, caxpy, ccopy, scnrm2, & slapy2 c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = | c | 'I'). NEV is the number of eigenvalues (closest | c | to the shift SIGMA) to be approximated. Since | c | the shift-invert mode is used, WHICH is set to | c | 'LM'. The user can modify NEV, NCV, SIGMA to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %----------------------------------------------------% c | Construct C = A - SIGMA*I, factor C in complex | c | arithmetic (using LAPACK subroutine cgttrf). The | c | matrix A is chosen to be the tridiagonal matrix | c | derived from standard central difference of the | c | 1-d convection diffusion operator - u``+ rho*u` on | c | the interval [0, 1] with zero Dirichlet boundary | c | condition. | c %----------------------------------------------------% c rho = (1.0E+1, 0.0E+0) h = one / cmplx(n+1) h2 = h*h s = rho / two c s1 = -one/h2 - s/h s2 = two/h2 - sigma s3 = -one/h2 + s/h c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call cgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in CNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of CNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1 ) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*I]*x | c | The user should supply his/her own linear | c | system solver here that takes | c | workd(ipntr(1)) as the input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------% c call ccopy( n, workd(ipntr(1)),1, workd(ipntr(2)), 1) c call cgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in CNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call cneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' else c nconv = iparam(5) do 60 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call caxpy(n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 60 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV2 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program cndrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------- c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Complex & v(n), w(n), rho, two, one, dd, dl, du, s, h, & h2 parameter (one = (1.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) common /convct/ rho c h = one / cmplx(n+1) h2 = h*h s = rho / two dd = two / h2 dl = -one/h2 - s/h du = -one/h2 + s/h c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/cndrv3.f000066400000000000000000000367341260666001200172670ustar00rootroot00000000000000 program cndrv3 c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized complex nonsymmetric eigenvalue c problem. c c We implement example three of ex-complex.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in regular mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... OP = inv[M]*A and B = M. c c ... Use mode 2 of CNAUPD. c c\BeginLib c c\Routines called: c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgttrf LAPACK tridiagonal factorization routine. c cgttrs LAPACK tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c scnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv3.F SID: 2.4 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex & ax(maxn), mx(maxn), d(maxncv), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), du2(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Complex & sigma, h Real & tol logical rvec c c %------------% c | Parameters | c %------------% c Complex & zero, one parameter (zero = (0.0E+0, 0.0E+0) , & one = (1.0E+0, 0.0E+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external caxpy, ccopy, scnrm2, cgttrf, cgttrs, & slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | cgttrf. | c %-----------------------------------------------------% c h = one / cmplx(n+1) do 20 j = 1, n-1 dl(j) = one*h dd(j) = (4.0E+0, 0.0E+0) *h du(j) = one*h 20 continue dd(n) = (4.0E+0, 0.0E+0) *h c call cgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in CNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of CNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call cgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs. ' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in CNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call cneupd ( rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, v, & ldv, iparam, ipntr, workd, workl, lworkl, rwork, & ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' c else c nconv = iparam(5) do 80 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call caxpy(n, -d(j), mx, 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated ', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Complex & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter (one = (1.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) , & rho = (1.0E+1, 0.0E+0) ) c c Compute the matrix vector multiplication y<---A*x c where A is the stiffness matrix formed by using piecewise linear c elements on [0,1]. c h = one / cmplx(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end c------------------------------------------------------------------------ subroutine mv (n, v, w) integer n, j Complex & v(n), w(n), one, four, h parameter (one = (1.0E+0, 0.0E+0) , & four = (4.0E+0, 0.0E+0) ) c c Compute the matrix vector multiplication y<---M*x c where M is the mass matrix formed by using piecewise linear elements c on [0,1]. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) c h = one / cmplx(n+1) call cscal(n, h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/cndrv4.f000066400000000000000000000420451260666001200172600ustar00rootroot00000000000000 program cndrv4 c c Simple program to illustrate the idea of reverse communication c in shift and invert mode for a generalized complex nonsymmetric c eigenvalue problem. c c We implement example four of ex-complex.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode, c where A and B are derived from a finite element discretization c of a 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... where the shift sigma is a complex number. c c ... OP = inv[A-SIGMA*M]*M and B = M. c c ... Use mode 3 of CNAUPD. c c\BeginLib c c\Routines called: c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgttrf LAPACK tridiagonal factorization routine. c cgttrs LAPACK tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c ccopy Level 1 BLAS that copies one vector to another. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv4.F SID: 2.4 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex & ax(maxn), mx(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), resid(maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) Real & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode Complex & rho, h, s, & sigma, s1, s2, s3 common /convct/ rho c Real & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, caxpy, ccopy, cgttrf, cgttrs, & slapy2 c c %------------% c | Parameters | c %------------% c Complex & one, zero, two, four, six parameter (one = (1.0E+0, 0.0E+0) , & zero = (0.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) , & four = (4.0E+0, 0.0E+0) , & six = (6.0E+0, 0.0E+0) ) c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to SIGMAR) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMA to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = one c c %--------------------------------------------------% c | Construct C = A - SIGMA*M in COMPLEX arithmetic. | c | Factor C in COMPLEX arithmetic (using LAPACK | c | subroutine cgttrf). The matrix A is chosen to be | c | the tridiagonal matrix derived from the standard | c | central difference discretization of the 1-d | c | convection-diffusion operator u``+ rho*u` on the | c | interval [0, 1] with zero Dirichlet boundary | c | condition. The matrix M is chosen to be the | c | symmetric tridiagonal matrix with 4.0 on the | c | diagonal and 1.0 on the off-diagonals. | c %--------------------------------------------------% c rho = (1.0E+1, 0.0E+0) h = one / cmplx(n+1) s = rho / two c s1 = -one/h - s - sigma*h/six s2 = two/h - four*sigma*h/six s3 = -one/h + s - sigma*h/six c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call cgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in CNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of CNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force starting vector into the range | c | of OP. The user should supply his/her | c | own matrix vector multiplication routine | c | and a linear system solver. The matrix | c | vector multiplication routine should take | c | workd(ipntr(1)) as the input. The final | c | result should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) call cgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | The user only need the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call ccopy( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call cgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %----------------------------% c | Error message, check the | c | documentation in CNAUPD | c %----------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call cneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, v, & ldv, iparam, ipntr, workd, workl, lworkl, rwork, & ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 80 j=1, nconv c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call caxpy(n, -d(j), mx, 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV4 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Complex & v(n), w(n), one, four, six, h parameter (one = (1.0E+0, 0.0E+0) , & four = (4.0E+0, 0.0E+0) , & six = (6.0E+0, 0.0E+0) ) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = ( four*v(1) + one*v(2) ) / six do 40 j = 2,n-1 w(j) = ( one*v(j-1) + four*v(j) + one*v(j+1) ) / six 40 continue w(n) = ( one*v(n-1) + four*v(n) ) / six c h = one / cmplx(n+1) call cscal(n, h, w, 1) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Complex & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter (one = (1.0E+0, 0.0E+0) , & two = (2.0E+0, 0.0E+0) ) common /convct/ rho c h = one / cmplx(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 40 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 40 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/zndrv1.f000066400000000000000000000352051260666001200173040ustar00rootroot00000000000000 program zndrv1 c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit squre [0,1]x[0,1] with zero Dirichlet boundary c condition. c c ... OP = A and B = I. c c ... Assume "call av (nx,x,y)" computes y = A*x c c ... Use mode 1 of ZNAUPD . c c\BeginLib c c\Routines called c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv1.F SID: 2.4 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex*16 & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Double precision & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex*16 & sigma Double precision & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zaxpy , dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of ZNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | ZNAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call zneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call zaxpy (n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program zndrv1 . | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c subroutine av (nx, v, w) integer nx, j, lo Complex*16 & v(nx*nx), w(nx*nx), one, h2 parameter (one = (1.0D+0, 0.0D+0) ) external zaxpy , tv c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / dcmplx ((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call zaxpy (nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy (nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call zaxpy (nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy (nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex*16 & x(nx), y(nx), h, h2, dd, dl, du c Complex*16 & one, rho parameter (one = (1.0D+0, 0.0D+0) , & rho = (1.0D+2, 0.0D+0) ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / dcmplx (nx+1) h2 = h*h dd = (4.0D+0, 0.0D+0) / h2 dl = -one/h2 - (5.0D-1, 0.0D+0) *rho/h du = -one/h2 + (5.0D-1, 0.0D+0) *rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/zndrv2.f000066400000000000000000000352041260666001200173040ustar00rootroot00000000000000 program zndrv2 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a standard complex nonsymmetric eigenvalue c problem. c c We implement example two of ex-complex.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the central difference discretization c of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition. c ... The shift sigma is a complex number. c c ... OP = inv[A-sigma*I] and B = I. c c ... Use mode 3 of ZNAUPD . c c\BeginLib c c\Routines called: c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgttrf LAPACK tridiagonal factorization routine. c zgttrs LAPACK tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c zcopy Level 1 BLAS that copies one vector to another. c dznrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv2.F SID: 2.6 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex*16 & ax(maxn), d(maxncv), resid(maxn), & v(ldv, maxncv), workd(3*maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode Complex*16 & h, h2, s, sigma, s1, s2, s3, rho common /convct/ rho c Double precision & tol logical rvec c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external zgttrf , zgttrs , zaxpy , zcopy , dznrm2 , & dlapy2 c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = | c | 'I'). NEV is the number of eigenvalues (closest | c | to the shift SIGMA) to be approximated. Since | c | the shift-invert mode is used, WHICH is set to | c | 'LM'. The user can modify NEV, NCV, SIGMA to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigma = zero c c %----------------------------------------------------% c | Construct C = A - SIGMA*I, factor C in complex | c | arithmetic (using LAPACK subroutine zgttrf ). The | c | matrix A is chosen to be the tridiagonal matrix | c | derived from standard central difference of the | c | 1-d convection diffusion operator - u``+ rho*u` on | c | the interval [0, 1] with zero Dirichlet boundary | c | condition. | c %----------------------------------------------------% c rho = (1.0D+1, 0.0D+0) h = one / dcmplx (n+1) h2 = h*h s = rho / two c s1 = -one/h2 - s/h s2 = two/h2 - sigma s3 = -one/h2 + s/h c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call zgttrf (n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in ZNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of ZNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in ZNAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1 ) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*I]*x | c | The user should supply his/her own linear | c | system solver here that takes | c | workd(ipntr(1)) as the input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------% c call zcopy ( n, workd(ipntr(1)),1, workd(ipntr(2)), 1) c call zgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call zneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' else c nconv = iparam(5) do 60 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call zaxpy (n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 60 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV2 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program zndrv2 . | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------- c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Complex*16 & v(n), w(n), rho, two, one, dd, dl, du, s, h, & h2 parameter (one = (1.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) common /convct/ rho c h = one / dcmplx (n+1) h2 = h*h s = rho / two dd = two / h2 dl = -one/h2 - s/h du = -one/h2 + s/h c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/zndrv3.f000066400000000000000000000370731260666001200173130ustar00rootroot00000000000000 program zndrv3 c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized complex nonsymmetric eigenvalue c problem. c c We implement example three of ex-complex.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in regular mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... OP = inv[M]*A and B = M. c c ... Use mode 2 of ZNAUPD . c c\BeginLib c c\Routines called: c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgttrf LAPACK tridiagonal factorization routine. c zgttrs LAPACK tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c dznrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv3.F SID: 2.4 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex*16 & ax(maxn), mx(maxn), d(maxncv), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), du2(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Complex*16 & sigma, h Double precision & tol logical rvec c c %------------% c | Parameters | c %------------% c Complex*16 & zero, one parameter (zero = (0.0D+0, 0.0D+0) , & one = (1.0D+0, 0.0D+0) ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external zaxpy , zcopy , dznrm2 , zgttrf , zgttrs , & dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | zgttrf . | c %-----------------------------------------------------% c h = one / dcmplx (n+1) do 20 j = 1, n-1 dl(j) = one*h dd(j) = (4.0D+0, 0.0D+0) *h du(j) = one*h 20 continue dd(n) = (4.0D+0, 0.0D+0) *h c call zgttrf (n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in ZNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of ZNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in ZNAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call zgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs. ' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in ZNAUPD . | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call zneupd ( rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, v, & ldv, iparam, ipntr, workd, workl, lworkl, rwork, & ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' c else c nconv = iparam(5) do 80 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call zaxpy (n, -d(j), mx, 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated ', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Complex*16 & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter (one = (1.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) , & rho = (1.0D+1, 0.0D+0) ) c c Compute the matrix vector multiplication y<---A*x c where A is the stiffness matrix formed by using piecewise linear c elements on [0,1]. c h = one / dcmplx (n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end c------------------------------------------------------------------------ subroutine mv (n, v, w) integer n, j Complex*16 & v(n), w(n), one, four, h parameter (one = (1.0D+0, 0.0D+0) , & four = (4.0D+0, 0.0D+0) ) c c Compute the matrix vector multiplication y<---M*x c where M is the mass matrix formed by using piecewise linear elements c on [0,1]. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) c h = one / dcmplx (n+1) call zscal (n, h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/COMPLEX/zndrv4.f000066400000000000000000000422101260666001200173010ustar00rootroot00000000000000 program zndrv4 c c Simple program to illustrate the idea of reverse communication c in shift and invert mode for a generalized complex nonsymmetric c eigenvalue problem. c c We implement example four of ex-complex.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode, c where A and B are derived from a finite element discretization c of a 1-dimensional convection-diffusion operator c (d^2u/dx^2) + rho*(du/dx) c on the interval [0,1] with zero boundary condition using c piecewise linear elements. c c ... where the shift sigma is a complex number. c c ... OP = inv[A-SIGMA*M]*M and B = M. c c ... Use mode 3 of ZNAUPD . c c\BeginLib c c\Routines called: c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgttrf LAPACK tridiagonal factorization routine. c zgttrs LAPACK tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c zcopy Level 1 BLAS that copies one vector to another. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv4.F SID: 2.4 DATE OF SID: 10/18/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Complex*16 & ax(maxn), mx(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), resid(maxn), & workev(2*maxncv), & workl(3*maxncv*maxncv+5*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) Double precision & rwork(maxn), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode Complex*16 & rho, h, s, & sigma, s1, s2, s3 common /convct/ rho c Double precision & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zaxpy , zcopy , zgttrf , zgttrs , & dlapy2 c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero, two, four, six parameter (one = (1.0D+0, 0.0D+0) , & zero = (0.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) , & four = (4.0D+0, 0.0D+0) , & six = (6.0D+0, 0.0D+0) ) c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to SIGMAR) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMA to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = one c c %--------------------------------------------------% c | Construct C = A - SIGMA*M in COMPLEX arithmetic. | c | Factor C in COMPLEX arithmetic (using LAPACK | c | subroutine zgttrf ). The matrix A is chosen to be | c | the tridiagonal matrix derived from the standard | c | central difference discretization of the 1-d | c | convection-diffusion operator u``+ rho*u` on the | c | interval [0, 1] with zero Dirichlet boundary | c | condition. The matrix M is chosen to be the | c | symmetric tridiagonal matrix with 4.0 on the | c | diagonal and 1.0 on the off-diagonals. | c %--------------------------------------------------% c rho = (1.0D+1, 0.0D+0) h = one / dcmplx (n+1) s = rho / two c s1 = -one/h - s - sigma*h/six s2 = two/h - four*sigma*h/six s3 = -one/h + s - sigma*h/six c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call zgttrf (n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in ZNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of ZNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in ZNAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force starting vector into the range | c | of OP. The user should supply his/her | c | own matrix vector multiplication routine | c | and a linear system solver. The matrix | c | vector multiplication routine should take | c | workd(ipntr(1)) as the input. The final | c | result should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) call zgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | The user only need the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call zcopy ( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call zgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %----------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %----------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call zneupd (rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, v, & ldv, iparam, ipntr, workd, workl, lworkl, rwork, & ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 80 j=1, nconv c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call zaxpy (n, -d(j), mx, 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV4 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Complex*16 & v(n), w(n), one, four, six, h parameter (one = (1.0D+0, 0.0D+0) , & four = (4.0D+0, 0.0D+0) , & six = (6.0D+0, 0.0D+0) ) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = ( four*v(1) + one*v(2) ) / six do 40 j = 2,n-1 w(j) = ( one*v(j-1) + four*v(j) + one*v(j+1) ) / six 40 continue w(n) = ( one*v(n-1) + four*v(n) ) / six c h = one / dcmplx (n+1) call zscal (n, h, w, 1) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Complex*16 & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter (one = (1.0D+0, 0.0D+0) , & two = (2.0D+0, 0.0D+0) ) common /convct/ rho c h = one / dcmplx (n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 40 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 40 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/Makefile.am000066400000000000000000000001011260666001200166210ustar00rootroot00000000000000SUBDIRS = BAND COMPLEX NONSYM SIMPLE SVD SYM EXTRA_DIST = README arpack-ng-3.3.0/EXAMPLES/NONSYM/000077500000000000000000000000001260666001200156205ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/NONSYM/Makefile.am000066400000000000000000000012601260666001200176530ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SNDRV = sndrv1 sndrv2 sndrv3 sndrv4 sndrv5 sndrv6 DNDRV = dndrv1 dndrv2 dndrv3 dndrv4 dndrv5 dndrv6 NONSYM = $(SNDRV) $(DNDRV) check_PROGRAMS = $(NONSYM) TESTS = $(check_PROGRAMS) EXTRA_DIST = README # Simple nonsymmetric problem using single precision sndrv1_SOURCES = sndrv1.f sndrv2_SOURCES = sndrv2.f sndrv3_SOURCES = sndrv3.f sndrv4_SOURCES = sndrv4.f sndrv5_SOURCES = sndrv5.f sndrv6_SOURCES = sndrv6.f # Simple nonsymmetric problem using double precision dndrv1_SOURCES = dndrv1.f dndrv2_SOURCES = dndrv2.f dndrv3_SOURCES = dndrv3.f dndrv4_SOURCES = dndrv4.f dndrv5_SOURCES = dndrv5.f dndrv6_SOURCES = dndrv6.f arpack-ng-3.3.0/EXAMPLES/NONSYM/README000066400000000000000000000042171260666001200165040ustar00rootroot000000000000001. Purpose ------- This directory contains example drivers that call ARPACK subroutines [s,d]naupd.f and [s,d]neupd.f to solve real NONSYMMETRIC eigenvalue problems using regular, inverse or shift-invert modes. These drivers illustrate how to set various ARPACK parameters to solve different problems in different modes. They provide a guideline on how to use ARPACK's reverse communication interface. The user may modify any one of these drivers, and provide his/her own matrix vector multiplication routine to solve the problem of his/her own interest. 2. Naming convention ----------------- The name for each driver has the form 'XndrvN.f', where X - is 's' (single precision) or 'd' (double precision) N - is a number between 1 and 6. If N = 1, the driver solves a STANDARD eigenvalue problem in REGULAR mode. N = 2, the driver solves a STANDARD eigenvalue problem in SHIFT-INVERT mode with a REAL shift. N = 3, the driver solves a GENERALIZED eigenvalue problem in INVERSE mode. N = 4, the driver solves a GENERALIZED eigenvalue problem in SHIFT-INVERT mode with a REAL shift. These are 4 commonly used drivers. For shift-invert (N=2,4) mode the user needs to supply a linear system solver to perform y=inv[A-sigma*B]*x. If N > 4, shift-invert is used with a complex shift whose imaginary part is nonzero. If N = 5, the driver solves a GENERALIZED eigenvalue problem using mode 3 of [s,d]naupd. N = 6. the driver solves a GENERALIZED eigenvalue problem using mode 4 of [s,d]naupd. These two drivers require the user to provide COMPLEX arithmetic linear system solver. For more information on the use of complex shift, see the following reference: B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for Real Matrices", Linear Algebra and its Applications, vol 88/89, pp 575-595, (1987). 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make sndrv1". Then execute using "sndrv1". arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv1.f000066400000000000000000000403751260666001200171760ustar00rootroot00000000000000 program dndrv1 c c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square [0,1]x[0,1] with zero Dirichlet boundary c condition. c c ... OP = A and B = I. c c ... Assume "call av (nx,x,y)" computes y = A*x.c c c ... Use mode 1 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv1.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) call daxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(nx, v(1,j+1), ax) call daxpy(n, -d(j,2), v(1,j), 1, ax, 1) call daxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV1 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv1. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c subroutine av (nx, v, w) integer nx, j, lo Double precision & v(nx*nx), w(nx*nx), one, h2 parameter (one = 1.0D+0) external daxpy c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c h2 = one / dble((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call daxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), h, h2, dd, dl, du c Double precision & one, zero, rho parameter (one = 1.0D+0, zero = 0.0D+0, & rho = 0.0D+0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / dble(nx+1) h2 = h*h dd = 4.0D+0 / h2 dl = -one / h2 - 5.0D-1*rho / h du = -one / h2 + 5.0D-1*rho / h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv2.f000066400000000000000000000375611260666001200172020ustar00rootroot00000000000000 program dndrv2 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a standard nonsymmetric eigenvalue problem. c c We implement example two of ex-nonsym.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the centered difference discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition. c c ... The shift sigma is a real number. c c ... OP = inv[A-sigma*I] and B = I. c c ... Use mode 3 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv2.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Double precision & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv, maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Double precision & tol, h, s, & sigmar, sigmai, s1, s2, s3 logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, rho common /convct/ rho parameter (one = 1.0D+0, zero = 0.0D+0, & two = 2.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & ddot, dnrm2, dlapy2 external dgttrf, dgttrs, ddot, dnrm2, dlapy2 c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = | c | 'I'). NEV is the number of eigenvalues (closest | c | to the shift SIGMAR) to be approximated. Since | c | the shift-invert mode is used, WHICH is set to | c | 'LM'. The user can modify NEV, NCV, SIGMAR to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 1.0D+0 sigmai = 0.0D+0 c c %----------------------------------------------------% c | Construct C = A - SIGMA*I in real arithmetic, and | c | factor C in real arithmetic using LAPACK | c | subroutine dgttrf. The matrix A is chosen to be | c | the tridiagonal matrix derived from standard | c | central difference of the 1-d convection diffusion | c | operator u" + rho*u' on the interval [0, 1] with | c | zero Dirichlet boundary condition. | c %----------------------------------------------------% c rho = 1.0D+1 h = one / dble(n+1) s = rho*h / two c s1 = -one-s s2 = two - sigmar s3 = -one+s c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call dgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if ( ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*I]*x | c | The user should supply his/her own linear | c | system solver here that takes | c | workd(ipntr(1)) as the input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------% c call dcopy( n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) c call dgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) call daxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(n, v(1,j+1), ax) call daxpy(n, -d(j,2), v(1,j), 1, ax, 1) call daxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV2 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------- c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), rho, two, one, dd, dl, du, s, h common /convct/ rho parameter (one = 1.0D+0, two = 2.0D+0 ) c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived from c the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c c h = one / dble(n+1) s = rho *h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv3.f000066400000000000000000000413561260666001200172000ustar00rootroot00000000000000 program dndrv3 c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c c ... So OP = inv[M]*A and B = M. c c ... Use mode 2 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dpttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c dpttrs LAPACK symmetric positive definite tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv3.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Double precision & tol, sigmar, sigmai, h logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero, one parameter (zero = 0.0D+0, one = 1.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Double precision & dnrm2, dlapy2 external daxpy, dnrm2, dpttrf, dpttrs, dlapy2 c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %------------------------------------------------% c | M is the mass matrix formed by using piecewise | c | linear elements on [0,1]. | c %------------------------------------------------% c h = one / dble(n+1) do 20 j = 1, n-1 md(j) = 4.0D+0*h me(j) = one*h 20 continue md(n) = 4.0D+0*h c call dpttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call dpttrs(n, 1, md, me, workd(ipntr(2)), n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call daxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1)**2 call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call daxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV3 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv3. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter ( rho = 1.0D+1, one = 1.0D+0, & two = 2.0D+0) c c Compute the matrix vector multiplication y<---A*x c where A is stiffness matrix obtained from the finite element c discretization of the 1-dimensional convection diffusion operator c d^2u/dx^2 + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition using c linear elements. c h = one / dble(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end c------------------------------------------------------------------------ subroutine mv (n, v, w) integer n, j Double precision & v(n), w(n), one, four, h parameter ( one = 1.0D+0, four = 4.0D+0) c c Compute the matrix vector multiplication y<---M*x c where M is the mass matrix formed by using piecewise linear c elements on [0,1]. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) c h = one / dble(n+1) call dscal(n, h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv4.f000066400000000000000000000464401260666001200172000ustar00rootroot00000000000000 program dndrv4 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue c problem. c c We implement example four of ex-nonsym.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c c ... The shift sigma is a real number. c c ... OP = inv[A-SIGMA*M]*M and B = M. c c ... Use mode 3 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal linear system solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Double precision & tol, h, s, & sigmar, sigmai, s1, s2, s3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & ddot, dnrm2, dlapy2 external ddot, dnrm2, dlapy2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %------------% c | Parameters | c %------------% c Double precision & one, zero, two, six, rho common /convct/ rho parameter (one = 1.0D+0, zero = 0.0D+0, & two = 2.0D+0, six = 6.0D+0) c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to SIGMAR) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMAR to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = one sigmai = zero c c %--------------------------------------------------% c | Construct C = A - SIGMA*M in real arithmetic, | c | and factor C in real arithmetic (using LAPACK | c | subroutine dgttrf). The matrix A is chosen to be | c | the tridiagonal matrix derived from the standard | c | central difference discretization of the 1-d | c | convection-diffusion operator u" + rho*u' on the | c | interval [0, 1] with zero Dirichlet boundary | c | condition. The matrix M is the mass matrix | c | formed by using piecewise linear elements on | c | [0,1]. | c %--------------------------------------------------% c rho = 1.0D+1 h = one / dble(n+1) s = rho / two c s1 = -one/h - s - sigmar*h/six s2 = two/h - 4.0D+0*sigmar*h/six s3 = -one/h + s - sigmar*h/six c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call dgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force starting vector into the range | c | of OP. The user should supply his/her | c | own matrix vector multiplication routine | c | and a linear system solver. The matrix | c | vector multiplication routine should take | c | workd(ipntr(1)) as the input. The final | c | result should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) call dgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | The user only need the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call dcopy( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call daxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call daxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV4 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv4. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Double precision & v(n), w(n), one, four, six, h parameter (one = 1.0D+0, four = 4.0D+0, six = 6.0D+0) c c Compute the matrix vector multiplication y<---M*x c where M is mass matrix formed by using piecewise linear elements c on [0,1]. c w(1) = ( four*v(1) + one*v(2) ) / six do 10 j = 2,n-1 w(j) = ( one*v(j-1) + four*v(j) + one*v(j+1) ) / six 10 continue w(n) = ( one*v(n-1) + four*v(n) ) / six c h = one / dble(n+1) call dscal(n, h, w, 1) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, dd, dl, du, s, h, rho common /convct/ rho parameter (one = 1.0D+0, two = 2.0D+0) c c Compute the matrix vector multiplication y<---A*x c where A is obtained from the finite element discretization of the c 1-dimensional convection diffusion operator c d^u/dx^2 + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c This routine is only used in residual calculation. c h = one / dble(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv5.f000066400000000000000000000533051260666001200171770ustar00rootroot00000000000000 program dndrv5 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue problem. c c We implement example five of ex-nonsym.doc in DOCUMENTS directory c c\Example-5 c c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode c The matrix A is the tridiagonal matrix with 2 on the diagonal, c -2 on the subdiagonal and 3 on the superdiagonal. The matrix M c is the tridiagonal matrix with 4 on the diagonal and 1 on the c off-diagonals. c ... The shift sigma is a complex number (sigmar, sigmai). c ... OP = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M and B = M. c ... Use mode 3 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgttrf LAPACK complex matrix factorization routine. c zgttrs LAPACK complex linear system solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector c av Matrix vector subroutine that computes A*x. c mv Matrix vector subroutine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv5.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) Complex*16 & cdd(maxn), cdl(maxn), cdu(maxn), & cdu2(maxn), ctemp(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Double precision & tol, numr, numi, denr, deni, sigmar, sigmai Complex*16 & c1, c2, c3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c external zgttrf, zgttrs Double precision & ddot, dnrm2, dlapy2 external ddot, dnrm2, dlapy2 c c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %--------------------% c | Intrinsic Function | c %--------------------% c intrinsic dble, dcmplx, abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to the shift (SIGMAR,SIGMAI)) to be approximated. | c | Since the shift-invert mode is used, WHICH is set | c | to 'LM'. The user can modify NEV, NCV, SIGMAR, | c | SIGMAI to solve problems of different sizes, and | c | to get different parts of the spectrum. However, | c | The following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0D-1 sigmai = 6.0D-1 c c %---------------------------------------------------% c | Construct C = A - (SIGMAR,SIGMAI)*M in complex | c | arithmetic, and factor C in complex arithmetic | c | (using LAPACK subroutine zgttrf). The matrix A is | c | chosen to be the tridiagonal matrix with -2 on | c | the subdiagonal, 2 on the diagonal and 3 on the | c | superdiagonal. The matrix M is chosen to the | c | symmetric tridiagonal matrix with 4 on the | c | diagonal and 1 on the off-diagonals. | c %---------------------------------------------------% c c1 = dcmplx(-2.0D+0-sigmar, -sigmai) c2 = dcmplx( 2.0D+0-4.0D+0*sigmar, -4.0D+0*sigmai) c3 = dcmplx( 3.0D+0-sigmar, -sigmai) c do 10 j = 1, n-1 cdl(j) = c1 cdd(j) = c2 cdu(j) = c3 10 continue cdd(n) = c2 c call zgttrf(n, cdl, cdd, cdu, cdu2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV5.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %-------------------------------------------------------% c | Perform | c | y <--- OP*x = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | to force starting vector into the range of OP. The | c | user should supply his/her own matrix vector | c | multiplication routine and a complex linear system | c | solver. The matrix vector multiplication routine | c | should take workd(ipntr(1)) as the input. The final | c | result (a real vector) should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) do 30 j = 1, n ctemp(j) = dcmplx(workd(ipntr(2)+j-1)) 30 continue c call zgttrs('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV5.' print*, ' ' go to 9000 end if do 40 j = 1, n workd(ipntr(2)+j-1) = dble(ctemp(j)) 40 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-------------------------------------------------------% c | Perform | c | y <--- OP*x = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | M*x has been saved in workd(ipntr(3)). The user only | c | needs the complex linear system solver here that | c | takes complex[workd(ipntr(3))] as input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------------------% c do 50 j = 1,n ctemp(j) = dcmplx(workd(ipntr(3)+j-1)) 50 continue call zgttrs ('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV5.' print*, ' ' go to 9000 end if do 60 j = 1, n workd(ipntr(2)+j-1) = dble(ctemp(j)) 60 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c c %------------------------------------------% c | Either we have convergence, or there is | c | an error. | c %------------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 70 j=1,nconv c c %-------------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original problem.| c %-------------------------------------% c if ( d(j,2) .eq. zero ) then c c %---------------------------% c | Eigenvalue is real. | c | Compute d = x'(Ax)/x'(Mx).| c %---------------------------% c call av(n, v(1,j), ax ) numr = ddot(n, v(1,j), 1, ax, 1) call mv(n, v(1,j), ax ) denr = ddot(n, v(1,j), 1, ax, 1) d(j,1) = numr / denr c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %----------------% c | Compute x'(Ax) | c %----------------% call av(n, v(1,j), ax ) numr = ddot(n, v(1,j), 1, ax, 1) numi = ddot(n, v(1,j+1), 1, ax, 1) call av(n, v(1,j+1), ax) numr = numr + ddot(n,v(1,j+1),1,ax,1) numi = -numi + ddot(n,v(1,j),1,ax,1) c c %----------------% c | Compute x'(Mx) | c %----------------% c call mv(n, v(1,j), ax ) denr = ddot(n, v(1,j), 1, ax, 1) deni = ddot(n, v(1,j+1), 1, ax, 1) call mv(n, v(1,j+1), ax) denr = denr + ddot(n,v(1,j+1),1,ax,1) deni = -deni + ddot(n,v(1,j),1, ax,1) c c %----------------% c | d=x'(Ax)/x'(Mx)| c %----------------% c d(j,1) = (numr*denr+numi*deni) / & dlapy2(denr, deni) d(j,2) = (numi*denr-numr*deni) / & dlapy2(denr, deni) first = .false. c else c c %------------------------------% c | Get the second eigenvalue of | c | the conjugate pair by taking | c | the conjugate of the last | c | eigenvalue computed. | c %------------------------------% c d(j,1) = d(j-1,1) d(j,2) = -d(j-1,2) first = .true. c end if c 70 continue c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c first = .true. do 80 j=1, nconv c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call daxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call daxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 80 continue c c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV5 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv5. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Double precision & v(n), w(n), one, four parameter (one = 1.0D+0, four = 4.0D+0) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), three, two parameter (three = 3.0D+0, two = 2.0D+0) c c Compute the matrix vector multiplication y<---A*x c where M is a n by n symmetric tridiagonal matrix with 2 on the c diagonal, -2 on the subdiagonal and 3 on the superdiagonal. c w(1) = two*v(1) + three*v(2) do 10 j = 2,n-1 w(j) = -two*v(j-1) + two*v(j) + three*v(j+1) 10 continue w(n) = -two*v(n-1) + two*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/dndrv6.f000066400000000000000000000535011260666001200171760ustar00rootroot00000000000000 program dndrv6 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue problem. c c We implement example six of ex-nonsym.doc in DOCUMENTS directory c c\Example-6 c c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode c The matrix A is the tridiagonal matrix with 2 on the diagonal, c -2 on the subdiagonal and 3 on the superdiagonal. The matrix M c is the tridiagonal matrix with 4 on the diagonal and 1 on the c off-diagonals. c ... The shift sigma is a complex number (sigmar, sigmai). c ... OP = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M and B = M. c ... Use mode 4 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c zgttrf LAPACK complex matrix factorization routine. c zgttrs LAPACK complex linear system solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c ddot Level 1 BLAS that computes the dot product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector subroutine that computes A*x. c mv Matrix vector subroutine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv6.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) Complex*16 & cdd(maxn), cdl(maxn), cdu(maxn), & cdu2(maxn), ctemp(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Double precision & tol, numr, numi, denr, deni, sigmar, sigmai Complex*16 & c1, c2, c3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c external zgttrf, zgttrs Double precision & ddot, dnrm2, dlapy2 external ddot, dnrm2, dlapy2 c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %--------------------% c | Intrinsic Function | c %--------------------% c intrinsic dimag, dcmplx, abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to the shift (SIGMAR,SIGMAI)) to be approximated. | c | Since the shift-invert mode is used, WHICH is set | c | to 'LM'. The user can modify NEV, NCV, SIGMA to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0D-1 sigmai = 6.0D-1 c c %----------------------------------------------------% c | Construct C = A - (SIGMAR,SIGMAI)*M in complex | c | arithmetic, and factor C in complex arithmetic | c | (using LAPACK subroutine zgttrf). The matrix A is | c | chosen to be the tridiagonal matrix with -2 on the | c | subdiagonal, 2 on the diagonal and 3 on the | c | superdiagonal. The matrix M is chosen to be the | c | symmetric tridiagonal matrix with 4 on the | c | diagonal and 1 on the off-diagonals. | c %----------------------------------------------------% c c1 = dcmplx(-2.0D+0-sigmar, -sigmai) c2 = dcmplx( 2.0D+0-4.0D+0*sigmar, -4.0D+0*sigmai) c3 = dcmplx( 3.0D+0-sigmar, -sigmai) c do 10 j = 1, n-1 cdl(j) = c1 cdd(j) = c2 cdu(j) = c3 10 continue cdd(n) = c2 c call zgttrf(n, cdl, cdd, cdu, cdu2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV6.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %------------------------------------------------------------% c | Perform | c | y <--- OP*x = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | to force starting vector into the range of OP. The user | c | should supply his/her own matrix vector multiplication | c | routine and a complex linear system solver. The matrix | c | vector multiplication routine should take workd(ipntr(1)) | c | as the input. The final result (a real vector) should be | c | returned to workd(ipntr(2)). | c %------------------------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) do 30 j = 1, n ctemp(j) = dcmplx(workd(ipntr(2)+j-1)) 30 continue c call zgttrs('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, maxn, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV6.' print*, ' ' go to 9000 end if do 40 j = 1, n workd(ipntr(2)+j-1) = dimag(ctemp(j)) 40 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %------------------------------------------------------------% c | Perform | c | y <--- OP*x = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | M*x has been saved in workd(ipntr(3)). The user only need | c | the complex linear system solver here that takes | c | complex[workd(ipntr(3))] as input, and returns the result | c | to workd(ipntr(2)). | c %------------------------------------------------------------% c do 50 j = 1,n ctemp(j) = dcmplx(workd(ipntr(3)+j-1)) 50 continue call zgttrs ('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, maxn, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV6.' print*, ' ' go to 9000 end if do 60 j = 1, n workd(ipntr(2)+j-1) = dimag(ctemp(j)) 60 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 70 j=1, nconv c c %-------------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original problem.| c %-------------------------------------% c if ( d(j,2) .eq. zero) then c c %----------------------------% c | Eigenvalue is real. | c | Compute d = x'(Ax)/x'(Mx). | c %----------------------------% c call av(n, v(1,j), ax ) numr = ddot(n, v(1,j), 1, ax, 1) call mv(n, v(1,j), ax ) denr = ddot(n, v(1,j), 1, ax, 1) d(j,1) = numr / denr c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %----------------% c | Compute x'(Ax) | c %----------------% c call av(n, v(1,j), ax ) numr = ddot(n, v(1,j), 1, ax, 1) numi = ddot(n, v(1,j+1), 1, ax, 1) call av(n, v(1,j+1), ax) numr = numr + ddot(n,v(1,j+1),1,ax,1) numi = -numi + ddot(n,v(1,j),1,ax,1) c c %----------------% c | Compute x'(Mx) | c %----------------% c call mv(n, v(1,j), ax ) denr = ddot(n, v(1,j), 1, ax, 1) deni = ddot(n, v(1,j+1), 1, ax, 1) call mv(n, v(1,j+1), ax) denr = denr + ddot(n,v(1,j+1),1,ax,1) deni = -deni + ddot(n,v(1,j),1, ax,1) c c %----------------% c | d=x'(Ax)/x'(Mx)| c %----------------% c d(j,1) = (numr*denr+numi*deni) / & dlapy2(denr, deni) d(j,2) = (numi*denr-numr*deni) / & dlapy2(denr, deni) first = .false. c else c c %------------------------------% c | Get the second eigenvalue of | c | the conjugate pair by taking | c | the conjugate of the last | c | eigenvalue computed. | c %------------------------------% c d(j,1) = d(j-1,1) d(j,2) = -d(j-1,2) first = .true. c end if c 70 continue c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c first = .true. nconv = iparam(5) do 80 j=1, nconv c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call daxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call daxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call daxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV6 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dndrv6. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Double precision & v(n), w(n), one, four parameter (one = 1.0D+0, four = 4.0D+0) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), three, two parameter (three = 3.0D+0, two = 2.0D+0) c c Compute the matrix vector multiplication y<---A*x c where M is a n by n symmetric tridiagonal matrix with 2 on the c diagonal, -2 on the subdiagonal and 3 on the superdiagonal. c w(1) = two*v(1) + three*v(2) do 10 j = 2,n-1 w(j) = -two*v(j-1) + two*v(j) + three*v(j+1) 10 continue w(n) = -two*v(n-1) + two*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv1.f000066400000000000000000000402511260666001200172060ustar00rootroot00000000000000 program sndrv1 c c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square [0,1]x[0,1] with zero Dirichlet boundary c condition. c c ... OP = A and B = I. c c ... Assume "call av (nx,x,y)" computes y = A*x.c c c ... Use mode 1 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv1.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Real & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(nx, v(1,j+1), ax) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV1 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv1. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c subroutine av (nx, v, w) integer nx, j, lo Real & v(nx*nx), w(nx*nx), one, h2 parameter (one = 1.0E+0) external saxpy c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c h2 = one / real((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call saxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), h, h2, dd, dl, du c Real & one, zero, rho parameter (one = 1.0E+0, zero = 0.0E+0, & rho = 0.0E+0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / real(nx+1) h2 = h*h dd = 4.0E+0 / h2 dl = -one / h2 - 5.0E-1*rho / h du = -one / h2 + 5.0E-1*rho / h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv2.f000066400000000000000000000374651260666001200172240ustar00rootroot00000000000000 program sndrv2 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a standard nonsymmetric eigenvalue problem. c c We implement example two of ex-nonsym.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the centered difference discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition. c c ... The shift sigma is a real number. c c ... OP = inv[A-sigma*I] and B = I. c c ... Use mode 3 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv2.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Real & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv, maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Real & tol, h, s, & sigmar, sigmai, s1, s2, s3 logical first, rvec c c %------------% c | Parameters | c %------------% c Real & one, zero, two, rho common /convct/ rho parameter (one = 1.0E+0, zero = 0.0E+0, & two = 2.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & sdot, snrm2, slapy2 external sgttrf, sgttrs, sdot, snrm2, slapy2 c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = | c | 'I'). NEV is the number of eigenvalues (closest | c | to the shift SIGMAR) to be approximated. Since | c | the shift-invert mode is used, WHICH is set to | c | 'LM'. The user can modify NEV, NCV, SIGMAR to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV2: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' sigmar = 1.0E+0 sigmai = 0.0E+0 c c %----------------------------------------------------% c | Construct C = A - SIGMA*I in real arithmetic, and | c | factor C in real arithmetic using LAPACK | c | subroutine sgttrf. The matrix A is chosen to be | c | the tridiagonal matrix derived from standard | c | central difference of the 1-d convection diffusion | c | operator u" + rho*u' on the interval [0, 1] with | c | zero Dirichlet boundary condition. | c %----------------------------------------------------% c rho = 1.0E+1 h = one / real(n+1) s = rho*h / two c s1 = -one-s s2 = two - sigmar s3 = -one+s c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call sgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if ( ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*I]*x | c | The user should supply his/her own linear | c | system solver here that takes | c | workd(ipntr(1)) as the input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------% c call scopy( n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) c call sgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV2.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(n, v(1,j+1), ax) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV2 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------- c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Real & v(n), w(n), rho, two, one, dd, dl, du, s, h common /convct/ rho parameter (one = 1.0E+0, two = 2.0E+0 ) c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived from c the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c c h = one / real(n+1) s = rho *h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv3.f000066400000000000000000000412461260666001200172150ustar00rootroot00000000000000 program sndrv3 c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c c ... So OP = inv[M]*A and B = M. c c ... Use mode 2 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c spttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c spttrs LAPACK symmetric positive definite tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv3.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Real & tol, sigmar, sigmai, h logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero, one parameter (zero = 0.0E+0, one = 1.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Real & snrm2, slapy2 external saxpy, snrm2, spttrf, spttrs, slapy2 c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %------------------------------------------------% c | M is the mass matrix formed by using piecewise | c | linear elements on [0,1]. | c %------------------------------------------------% c h = one / real(n+1) do 20 j = 1, n-1 md(j) = 4.0E+0*h me(j) = one*h 20 continue md(n) = 4.0E+0*h c call spttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call spttrs(n, 1, md, me, workd(ipntr(2)), n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1)**2 call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV3 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv3. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine av (n, v, w) integer n, j Real & v(n), w(n), one, two, dd, dl, du, s, h, rho parameter ( rho = 1.0E+1, one = 1.0E+0, & two = 2.0E+0) c c Compute the matrix vector multiplication y<---A*x c where A is stiffness matrix obtained from the finite element c discretization of the 1-dimensional convection diffusion operator c d^2u/dx^2 + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition using c linear elements. c h = one / real(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end c------------------------------------------------------------------------ subroutine mv (n, v, w) integer n, j Real & v(n), w(n), one, four, h parameter ( one = 1.0E+0, four = 4.0E+0) c c Compute the matrix vector multiplication y<---M*x c where M is the mass matrix formed by using piecewise linear c elements on [0,1]. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) c h = one / real(n+1) call sscal(n, h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv4.f000066400000000000000000000463301260666001200172150ustar00rootroot00000000000000 program sndrv4 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue c problem. c c We implement example four of ex-nonsym.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A and B are derived from the finite element discretization c of the 1-dimensional convection-diffusion operator c (d^2u / dx^2) + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c c ... The shift sigma is a real number. c c ... OP = inv[A-SIGMA*M]*M and B = M. c c ... Use mode 3 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal linear system solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & dd(maxn), dl(maxn), du(maxn), & du2(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Real & tol, h, s, & sigmar, sigmai, s1, s2, s3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & sdot, snrm2, slapy2 external sdot, snrm2, slapy2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %------------% c | Parameters | c %------------% c Real & one, zero, two, six, rho common /convct/ rho parameter (one = 1.0E+0, zero = 0.0E+0, & two = 2.0E+0, six = 6.0E+0) c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to SIGMAR) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMAR to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = one sigmai = zero c c %--------------------------------------------------% c | Construct C = A - SIGMA*M in real arithmetic, | c | and factor C in real arithmetic (using LAPACK | c | subroutine sgttrf). The matrix A is chosen to be | c | the tridiagonal matrix derived from the standard | c | central difference discretization of the 1-d | c | convection-diffusion operator u" + rho*u' on the | c | interval [0, 1] with zero Dirichlet boundary | c | condition. The matrix M is the mass matrix | c | formed by using piecewise linear elements on | c | [0,1]. | c %--------------------------------------------------% c rho = 1.0E+1 h = one / real(n+1) s = rho / two c s1 = -one/h - s - sigmar*h/six s2 = two/h - 4.0E+0*sigmar*h/six s3 = -one/h + s - sigmar*h/six c do 10 j = 1, n-1 dl(j) = s1 dd(j) = s2 du(j) = s3 10 continue dd(n) = s2 c call sgttrf(n, dl, dd, du, du2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force starting vector into the range | c | of OP. The user should supply his/her | c | own matrix vector multiplication routine | c | and a linear system solver. The matrix | c | vector multiplication routine should take | c | workd(ipntr(1)) as the input. The final | c | result should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) call sgttrs('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | The user only need the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call scopy( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgttrs ('N', n, 1, dl, dd, du, du2, ipiv, & workd(ipntr(2)), n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV4.' print*, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation in _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV4 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv4. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Real & v(n), w(n), one, four, six, h parameter (one = 1.0E+0, four = 4.0E+0, six = 6.0E+0) c c Compute the matrix vector multiplication y<---M*x c where M is mass matrix formed by using piecewise linear elements c on [0,1]. c w(1) = ( four*v(1) + one*v(2) ) / six do 10 j = 2,n-1 w(j) = ( one*v(j-1) + four*v(j) + one*v(j+1) ) / six 10 continue w(n) = ( one*v(n-1) + four*v(n) ) / six c h = one / real(n+1) call sscal(n, h, w, 1) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Real & v(n), w(n), one, two, dd, dl, du, s, h, rho common /convct/ rho parameter (one = 1.0E+0, two = 2.0E+0) c c Compute the matrix vector multiplication y<---A*x c where A is obtained from the finite element discretization of the c 1-dimensional convection diffusion operator c d^u/dx^2 + rho*(du/dx) c on the interval [0,1] with zero Dirichlet boundary condition c using linear elements. c This routine is only used in residual calculation. c h = one / real(n+1) s = rho / two dd = two / h dl = -one/h - s du = -one/h + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,n-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(n) = dl*v(n-1) + dd*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv5.f000066400000000000000000000531611260666001200172160ustar00rootroot00000000000000 program sndrv5 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue problem. c c We implement example five of ex-nonsym.doc in DOCUMENTS directory c c\Example-5 c c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode c The matrix A is the tridiagonal matrix with 2 on the diagonal, c -2 on the subdiagonal and 3 on the superdiagonal. The matrix M c is the tridiagonal matrix with 4 on the diagonal and 1 on the c off-diagonals. c ... The shift sigma is a complex number (sigmar, sigmai). c ... OP = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M and B = M. c ... Use mode 3 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgttrf LAPACK complex matrix factorization routine. c cgttrs LAPACK complex linear system solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector c av Matrix vector subroutine that computes A*x. c mv Matrix vector subroutine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv5.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) Complex & cdd(maxn), cdl(maxn), cdu(maxn), & cdu2(maxn), ctemp(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Real & tol, numr, numi, denr, deni, sigmar, sigmai Complex & c1, c2, c3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c external cgttrf, cgttrs Real & sdot, snrm2, slapy2 external sdot, snrm2, slapy2 c c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %--------------------% c | Intrinsic Function | c %--------------------% c intrinsic real, cmplx, abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to the shift (SIGMAR,SIGMAI)) to be approximated. | c | Since the shift-invert mode is used, WHICH is set | c | to 'LM'. The user can modify NEV, NCV, SIGMAR, | c | SIGMAI to solve problems of different sizes, and | c | to get different parts of the spectrum. However, | c | The following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0E-1 sigmai = 6.0E-1 c c %---------------------------------------------------% c | Construct C = A - (SIGMAR,SIGMAI)*M in complex | c | arithmetic, and factor C in complex arithmetic | c | (using LAPACK subroutine cgttrf). The matrix A is | c | chosen to be the tridiagonal matrix with -2 on | c | the subdiagonal, 2 on the diagonal and 3 on the | c | superdiagonal. The matrix M is chosen to the | c | symmetric tridiagonal matrix with 4 on the | c | diagonal and 1 on the off-diagonals. | c %---------------------------------------------------% c c1 = cmplx(-2.0E+0-sigmar, -sigmai) c2 = cmplx( 2.0E+0-4.0E+0*sigmar, -4.0E+0*sigmai) c3 = cmplx( 3.0E+0-sigmar, -sigmai) c do 10 j = 1, n-1 cdl(j) = c1 cdd(j) = c2 cdu(j) = c3 10 continue cdd(n) = c2 c call cgttrf(n, cdl, cdd, cdu, cdu2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV5.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %-------------------------------------------------------% c | Perform | c | y <--- OP*x = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | to force starting vector into the range of OP. The | c | user should supply his/her own matrix vector | c | multiplication routine and a complex linear system | c | solver. The matrix vector multiplication routine | c | should take workd(ipntr(1)) as the input. The final | c | result (a real vector) should be returned to | c | workd(ipntr(2)). | c %-------------------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) do 30 j = 1, n ctemp(j) = cmplx(workd(ipntr(2)+j-1)) 30 continue c call cgttrs('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV5.' print*, ' ' go to 9000 end if do 40 j = 1, n workd(ipntr(2)+j-1) = real(ctemp(j)) 40 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %-------------------------------------------------------% c | Perform | c | y <--- OP*x = Real_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | M*x has been saved in workd(ipntr(3)). The user only | c | needs the complex linear system solver here that | c | takes complex[workd(ipntr(3))] as input, and returns | c | the result to workd(ipntr(2)). | c %-------------------------------------------------------% c do 50 j = 1,n ctemp(j) = cmplx(workd(ipntr(3)+j-1)) 50 continue call cgttrs ('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, n, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV5.' print*, ' ' go to 9000 end if do 60 j = 1, n workd(ipntr(2)+j-1) = real(ctemp(j)) 60 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c c %------------------------------------------% c | Either we have convergence, or there is | c | an error. | c %------------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 70 j=1,nconv c c %-------------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original problem.| c %-------------------------------------% c if ( d(j,2) .eq. zero ) then c c %---------------------------% c | Eigenvalue is real. | c | Compute d = x'(Ax)/x'(Mx).| c %---------------------------% c call av(n, v(1,j), ax ) numr = sdot(n, v(1,j), 1, ax, 1) call mv(n, v(1,j), ax ) denr = sdot(n, v(1,j), 1, ax, 1) d(j,1) = numr / denr c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %----------------% c | Compute x'(Ax) | c %----------------% call av(n, v(1,j), ax ) numr = sdot(n, v(1,j), 1, ax, 1) numi = sdot(n, v(1,j+1), 1, ax, 1) call av(n, v(1,j+1), ax) numr = numr + sdot(n,v(1,j+1),1,ax,1) numi = -numi + sdot(n,v(1,j),1,ax,1) c c %----------------% c | Compute x'(Mx) | c %----------------% c call mv(n, v(1,j), ax ) denr = sdot(n, v(1,j), 1, ax, 1) deni = sdot(n, v(1,j+1), 1, ax, 1) call mv(n, v(1,j+1), ax) denr = denr + sdot(n,v(1,j+1),1,ax,1) deni = -deni + sdot(n,v(1,j),1, ax,1) c c %----------------% c | d=x'(Ax)/x'(Mx)| c %----------------% c d(j,1) = (numr*denr+numi*deni) / & slapy2(denr, deni) d(j,2) = (numi*denr-numr*deni) / & slapy2(denr, deni) first = .false. c else c c %------------------------------% c | Get the second eigenvalue of | c | the conjugate pair by taking | c | the conjugate of the last | c | eigenvalue computed. | c %------------------------------% c d(j,1) = d(j-1,1) d(j,2) = -d(j-1,2) first = .true. c end if c 70 continue c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c first = .true. do 80 j=1, nconv c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 80 continue c c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV5 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv5. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Real & v(n), w(n), one, four parameter (one = 1.0E+0, four = 4.0E+0) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Real & v(n), w(n), three, two parameter (three = 3.0E+0, two = 2.0E+0) c c Compute the matrix vector multiplication y<---A*x c where M is a n by n symmetric tridiagonal matrix with 2 on the c diagonal, -2 on the subdiagonal and 3 on the superdiagonal. c w(1) = two*v(1) + three*v(2) do 10 j = 2,n-1 w(j) = -two*v(j-1) + two*v(j) + three*v(j+1) 10 continue w(n) = -two*v(n-1) + two*v(n) return end arpack-ng-3.3.0/EXAMPLES/NONSYM/sndrv6.f000066400000000000000000000533551260666001200172240ustar00rootroot00000000000000 program sndrv6 c c Simple program to illustrate the idea of reverse communication c in shift-invert mode for a generalized nonsymmetric eigenvalue problem. c c We implement example six of ex-nonsym.doc in DOCUMENTS directory c c\Example-6 c c ... Suppose we want to solve A*x = lambda*B*x in shift-invert mode c The matrix A is the tridiagonal matrix with 2 on the diagonal, c -2 on the subdiagonal and 3 on the superdiagonal. The matrix M c is the tridiagonal matrix with 4 on the diagonal and 1 on the c off-diagonals. c ... The shift sigma is a complex number (sigmar, sigmai). c ... OP = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M and B = M. c ... Use mode 4 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c cgttrf LAPACK complex matrix factorization routine. c cgttrs LAPACK complex linear system solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c sdot Level 1 BLAS that computes the dot product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector subroutine that computes A*x. c mv Matrix vector subroutine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ndrv6.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), ipiv(maxn) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) Complex & cdd(maxn), cdl(maxn), cdu(maxn), & cdu2(maxn), ctemp(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode Real & tol, numr, numi, denr, deni, sigmar, sigmai Complex & c1, c2, c3 logical first, rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c external cgttrf, cgttrs Real & sdot, snrm2, slapy2 external sdot, snrm2, slapy2 c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %--------------------% c | Intrinsic Function | c %--------------------% c intrinsic aimag, cmplx, abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues (closest | c | to the shift (SIGMAR,SIGMAI)) to be approximated. | c | Since the shift-invert mode is used, WHICH is set | c | to 'LM'. The user can modify NEV, NCV, SIGMA to | c | solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _NDRV6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigmar = 4.0E-1 sigmai = 6.0E-1 c c %----------------------------------------------------% c | Construct C = A - (SIGMAR,SIGMAI)*M in complex | c | arithmetic, and factor C in complex arithmetic | c | (using LAPACK subroutine cgttrf). The matrix A is | c | chosen to be the tridiagonal matrix with -2 on the | c | subdiagonal, 2 on the diagonal and 3 on the | c | superdiagonal. The matrix M is chosen to be the | c | symmetric tridiagonal matrix with 4 on the | c | diagonal and 1 on the off-diagonals. | c %----------------------------------------------------% c c1 = cmplx(-2.0E+0-sigmar, -sigmai) c2 = cmplx( 2.0E+0-4.0E+0*sigmar, -4.0E+0*sigmai) c3 = cmplx( 3.0E+0-sigmar, -sigmai) c do 10 j = 1, n-1 cdl(j) = c1 cdd(j) = c2 cdu(j) = c3 10 continue cdd(n) = c2 c call cgttrf(n, cdl, cdd, cdu, cdu2, ipiv, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrf in _NDRV6.' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SNAUPD is used | c | (IPARAM(7) = 3). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------% c | M A I N L O O P(Reverse communication) | c %------------------------------------------% c 20 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1) then c c %------------------------------------------------------------% c | Perform | c | y <--- OP*x = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | to force starting vector into the range of OP. The user | c | should supply his/her own matrix vector multiplication | c | routine and a complex linear system solver. The matrix | c | vector multiplication routine should take workd(ipntr(1)) | c | as the input. The final result (a real vector) should be | c | returned to workd(ipntr(2)). | c %------------------------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) do 30 j = 1, n ctemp(j) = cmplx(workd(ipntr(2)+j-1)) 30 continue c call cgttrs('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, maxn, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV6.' print*, ' ' go to 9000 end if do 40 j = 1, n workd(ipntr(2)+j-1) = aimag(ctemp(j)) 40 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 1) then c c %------------------------------------------------------------% c | Perform | c | y <--- OP*x = Imaginary_Part{inv[A-(SIGMAR,SIGMAI)*M]*M*x} | c | M*x has been saved in workd(ipntr(3)). The user only need | c | the complex linear system solver here that takes | c | complex[workd(ipntr(3))] as input, and returns the result | c | to workd(ipntr(2)). | c %------------------------------------------------------------% c do 50 j = 1,n ctemp(j) = cmplx(workd(ipntr(3)+j-1)) 50 continue call cgttrs ('N', n, 1, cdl, cdd, cdu, cdu2, ipiv, & ctemp, maxn, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _gttrs in _NDRV6.' print*, ' ' go to 9000 end if do 60 j = 1, n workd(ipntr(2)+j-1) = aimag(ctemp(j)) 60 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c else if ( ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- M*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 20 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd.' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 70 j=1, nconv c c %-------------------------------------% c | Use Rayleigh Quotient to recover | c | eigenvalues of the original problem.| c %-------------------------------------% c if ( d(j,2) .eq. zero) then c c %----------------------------% c | Eigenvalue is real. | c | Compute d = x'(Ax)/x'(Mx). | c %----------------------------% c call av(n, v(1,j), ax ) numr = sdot(n, v(1,j), 1, ax, 1) call mv(n, v(1,j), ax ) denr = sdot(n, v(1,j), 1, ax, 1) d(j,1) = numr / denr c else if (first) then c c %------------------------% c | Eigenvalue is complex. | c | Compute the first one | c | of the conjugate pair. | c %------------------------% c c %----------------% c | Compute x'(Ax) | c %----------------% c call av(n, v(1,j), ax ) numr = sdot(n, v(1,j), 1, ax, 1) numi = sdot(n, v(1,j+1), 1, ax, 1) call av(n, v(1,j+1), ax) numr = numr + sdot(n,v(1,j+1),1,ax,1) numi = -numi + sdot(n,v(1,j),1,ax,1) c c %----------------% c | Compute x'(Mx) | c %----------------% c call mv(n, v(1,j), ax ) denr = sdot(n, v(1,j), 1, ax, 1) deni = sdot(n, v(1,j+1), 1, ax, 1) call mv(n, v(1,j+1), ax) denr = denr + sdot(n,v(1,j+1),1,ax,1) deni = -deni + sdot(n,v(1,j),1, ax,1) c c %----------------% c | d=x'(Ax)/x'(Mx)| c %----------------% c d(j,1) = (numr*denr+numi*deni) / & slapy2(denr, deni) d(j,2) = (numi*denr-numr*deni) / & slapy2(denr, deni) first = .false. c else c c %------------------------------% c | Get the second eigenvalue of | c | the conjugate pair by taking | c | the conjugate of the last | c | eigenvalue computed. | c %------------------------------% c d(j,1) = d(j-1,1) d(j,2) = -d(j-1,2) first = .true. c end if c 70 continue c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c first = .true. nconv = iparam(5) do 80 j=1, nconv c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j+1), mx) call saxpy(n, d(j,2), mx, 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(n, v(1,j+1), ax) call mv(n, v(1,j+1), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) call mv(n, v(1,j), mx) call saxpy(n, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 80 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and relative residuals') c end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NDRV6 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sndrv6. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector multiplication subroutine c subroutine mv (n, v, w) integer n, j Real & v(n), w(n), one, four parameter (one = 1.0E+0, four = 4.0E+0) c c Compute the matrix vector multiplication y<---M*x c where M is a n by n symmetric tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and superdiagonal. c w(1) = four*v(1) + one*v(2) do 10 j = 2,n-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(n) = one*v(n-1) + four*v(n) return end c------------------------------------------------------------------ subroutine av (n, v, w) integer n, j Real & v(n), w(n), three, two parameter (three = 3.0E+0, two = 2.0E+0) c c Compute the matrix vector multiplication y<---A*x c where M is a n by n symmetric tridiagonal matrix with 2 on the c diagonal, -2 on the subdiagonal and 3 on the superdiagonal. c w(1) = two*v(1) + three*v(2) do 10 j = 2,n-1 w(j) = -two*v(j-1) + two*v(j) + three*v(j+1) 10 continue w(n) = -two*v(n-1) + two*v(n) return end arpack-ng-3.3.0/EXAMPLES/README000066400000000000000000000106231260666001200154570ustar00rootroot000000000000001. Purpose ------- This directory contains example drivers that call ARPACK subroutines __aupd.f and __eupd.f to solve various eigenvalue problems using regular, shift-invert or other special modes (such as Cayley, Bucking etc.) These drivers illustrate how to set various ARPACK parameters to solve different problems in different modes. They provide a guideline on how to use ARPACK's reverse communication interface. The user may modify any one of these drivers, and supply his/her own matrix vector multiplication routine to solve the problem of his/her own interest. These drivers are installed in the following subdirectories. SIMPLE --- simple drivers for beginners. SYM --- drivers for symmetric eigenvalue problems NONSYM --- drivers for nonsymmetric eigenvalue problems COMPLEX --- drivers for eigenvalue problem with complex matrices BAND --- drivers for eigenvalue problem with BANDED matrices SVD --- drivers for computing singular values and vectors of a m by n matrix. 2. Getting started --------------- If you have never used ARPACK before, it might be a good idea to go into the subdirectory SIMPLE, and read one of the simple drivers [s,d]ssimp.f, [s,d]nsimp.f [c,z]nsimp.f first. The documentation explains how to use ARPACK in considerable detail. To run these drivers, you may use the makefile in that directory and issue, for example, "make sssimp", and then execute using "sssimp" The output should look like: _saupd: number of update iterations taken ----------------------------------------- 1 - 1: 5 _saupd: number of "converged" Ritz values ----------------------------------------- 1 - 1: 4 _saupd: final Ritz values ------------------------- 1 - 4: 8.912E+02 9.198E+02 9.198E+02 9.484E+02 _saupd: corresponding error bounds ---------------------------------- 1 - 4: 4.686E-11 1.905E-08 1.050E-10 5.700E-19 ========================================== = Symmetric implicit Arnoldi update code = = Version Number: 2.1 = = Version Date: 11/15/95 = ========================================== = Summary of timing statistics = ========================================== Total number update iterations = 5 Total number of OP*x operations = 78 Total number of B*x operations = 0 Total number of reorthogonalization steps = 78 Total number of iterative refinement steps = 0 Total number of restart steps = 0 Total time in user OP*x operation = 0.066667 Total time in user B*x operation = 0.000000 Total time in Arnoldi update routine = 1.166667 Total time in ssaup2 routine = 1.166667 Total time in basic Arnoldi iteration loop = 0.216667 Total time in reorthogonalization phase = 0.066667 Total time in (re)start vector generation = 0.000000 Total time in trid eigenvalue subproblem = 0.050000 Total time in getting the shifts = 0.000000 Total time in applying the shifts = 0.900000 Total time in convergence testing = 0.000000 Ritz values and relative residuals ---------------------------------- Col 1 Col 2 Row 1: 8.91167E+02 6.95597E-07 Row 2: 9.19781E+02 3.30156E-07 Row 3: 9.19781E+02 4.25717E-07 Row 4: 9.48395E+02 3.20519E-07 _SSIMP ====== Size of the matrix is 100 The number of Ritz values requested is 4 The number of Arnoldi vectors generated (NCV) is 20 What portion of the spectrum: LM The number of converged Ritz values is 4 The number of Implicit Arnoldi update iterations taken is 5 The number of OP*x is 78 The convergence criterion is 5.96046E-08 3. Convention ---------- The naming convention for each driver is explained in the README file in each subdirectory. 4. LAPACK & BLAS routines ---------------------- All ARPACK codes assume the use of LAPACK version 2.0 codes. LAPACK and BLAS routines needed for each driver program are listed at the beginning of the documentation in each driver program. arpack-ng-3.3.0/EXAMPLES/SIMPLE/000077500000000000000000000000001260666001200155665ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/SIMPLE/Makefile.am000066400000000000000000000005451260666001200176260ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SIMPLE = sssimp dssimp snsimp dnsimp cnsimp znsimp check_PROGRAMS = $(SIMPLE) TESTS = $(check_PROGRAMS) EXTRA_DIST = README debug.h sssimp_SOURCES = sssimp.f dssimp_SOURCES = dssimp.f snsimp_SOURCES = snsimp.f dnsimp_SOURCES = dnsimp.f cnsimp_SOURCES = cnsimp.f znsimp_SOURCES = znsimp.f arpack-ng-3.3.0/EXAMPLES/SIMPLE/README000066400000000000000000000015171260666001200164520ustar00rootroot000000000000001. Purpose ------- This directory contains simple example drivers that call ARPACK subroutine __aupd.f and __eupd.f to solve various eigenvalue problems using regular mode. These drivers illustrate how to use ARPACK in considerable detail. If you have never used ARPACK before, this is the place to start. 2. Naming Convention ----------------- The name for each driver has the form 'XYsimp.f', where X - is 's' (single precision) or 'd' (double precision) or 'c' (single complex) or 'z' (double complex) Y - is 's' (symmetric) or 'n' (nonsymmetric) Note: there is no simple driver specifically for hermitian complex. 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make sssimp". Then execute using "sssimp". arpack-ng-3.3.0/EXAMPLES/SIMPLE/cnsimp.f000066400000000000000000000506021260666001200172310ustar00rootroot00000000000000 program cnsimp c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is a general n by n complex matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine CNAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine CNEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-complex.doc in DOCUMENTS directory. c This codes implements c c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c ... OP = A and B = I. c ... Assume "call av (nx,x,y)" computes y = A*x c ... Use mode 1 of CNAUPD. c c\BeginLib c c\Routines called c cnaupd ARPACK reverse communication interface routine. c cneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nsimp.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(2*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Real & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv Complex & sigma Real & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & scnrm2, slapy2 external scnrm2, caxpy, slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting mcaupd = 1 | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 mcaitr = 0 mcapps = 0 mcaupd = 1 mcaup2 = 0 mceigh = 0 mceupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in CNAUPD for the | c | other options SM, LR, SR, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c | | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _NSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling CNAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from CNAUPD. (see usage below) | c | | c | It MUST initially be set to 0 before the first | c | call to CNAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID). | c | | c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of CNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse Communication Loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% call cnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | | c | y <--- A*x | c | | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector x , and returns the resulting | c | matrix-vector product y = A*x in the | c | array workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 c endif c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in CNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine CNEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1.) | c | | c %-------------------------------------------% c rvec = .true. c call cneupd (rvec, 'A', select, D, V, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %-----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D and the corresponding | c | eigenvectors are returned in the first | c | NCONV (=IPARAM(5)) columns of the two | c | dimensional array V if requested. Otherwise, | c | an orthogonal basis for the invariant | c | subspace corresponding to the eigenvalues in | c | D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call caxpy(n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real (d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = scnrm2(n, ax, 1) rd(j,3) = rd(j,3) / slapy2(rd(j,1),rd(j,2)) 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NSIMP ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program cnsimp. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c subroutine av (nx, v, w) integer nx, j, lo Complex & v(nx*nx), w(nx*nx), one, h2 parameter (one = (1.0E+0, 0.0E+0) ) external caxpy c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2-dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) c on the unit squqre with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / cmplx((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call caxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call caxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex & x(nx), y(nx), h, h2, dd, dl, du c Complex & one, rho parameter (one = (1.0E+0, 0.0E+0) , & rho = (1.0E+2, 0.0E+0) ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / cmplx(nx+1) h2 = h*h dd = (4.0E+0, 0.0E+0) / h2 dl = -one/h2 - (5.0E-1, 0.0E+0) *rho/h du = -one/h2 + (5.0E-1, 0.0E+0) *rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SIMPLE/debug.h000066400000000000000000000013511260666001200170250ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/EXAMPLES/SIMPLE/dnsimp.f000066400000000000000000000536421260666001200172410ustar00rootroot00000000000000 program dnsimp c c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is a n by n real nonsymmetric matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine DNAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine DNEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-nonsym.doc in DOCUMENTS directory. c This codes implements c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (nx,x,y)" computes y = A*x c ... Use mode 1 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nsimp.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting mnaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 mnaitr = 0 mnapps = 0 mnaupd = 1 mnaup2 = 0 mneigh = 0 mneupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization. | c | | c | 3) This is a standard problem. | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude. | c | (indicated by which = 'LM') | c | See documentation in DNAUPD for the | c | other options SM, LR, SR, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c | | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _NSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling DNAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from DNAUPD. (see usage below) | c | | c | It MUST initially be set to 0 before the first | c | call to DNAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID). | c | | c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- Op*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c endif c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine DNEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1,) | c | | c %-------------------------------------------% c rvec = .true. c call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %------------------------------------------------% c | The real parts of the eigenvalues are returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part are returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first | c | NCONV (= IPARAM(5)) columns of the two | c | dimensional array V if requested. Otherwise, | c | an orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %------------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (IPARAM(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) call daxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(nx, v(1,j+1), ax) call daxpy(n, -d(j,2), v(1,j), 1, ax, 1) call daxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real, Imag) and residual residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NSIMP ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dnsimp. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c subroutine av (nx, v, w) integer nx, j, lo Double precision & v(nx*nx), w(nx*nx), one, h2 parameter (one = 1.0D+0) external daxpy, tv c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has complex c eigenvalues. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / dble((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call daxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), h, dd, dl, du, h2 c Double precision & one, rho parameter (one = 1.0D+0, rho = 1.0D+2) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has complex c eigenvalues. c h = one / dble(nx+1) h2 = h*h dd = 4.0D+0 / h2 dl = -one/h2 - 5.0D-1*rho/h du = -one/h2 + 5.0D-1*rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SIMPLE/dssimp.f000066400000000000000000000473251260666001200172470ustar00rootroot00000000000000 program dssimp c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is an n by n real symmetric matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine DSAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine DSEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-sym.doc in DOCUMENTS directory. c This codes implements c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x c ... Use mode 1 of DSAUPD. c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ssimp.F SID: 2.6 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, $ ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, & j, nx, ishfts, maxitr, mode1, nconv logical rvec Double precision & tol, sigma c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external dnrm2, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting msaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 msgets = 0 msaitr = 0 msapps = 0 msaupd = 1 msaup2 = 0 mseigt = 0 mseupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in DSAUPD for the | c | other options SM, LA, SA, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _SSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling DSAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from DSAUPD. (See usage below.) | c | | c | It MUST initially be set to 0 before the first | c | call to DSAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID.) | c | | c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting PARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse communication loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in DSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine DSEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1.) | c | | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NCONV (=IPARAM(5)) columns of the | c | two dimensional array V if requested. | c | Otherwise, an orthogonal basis for the | c | invariant subspace corresponding to the | c | eigenvalues in D is returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = dnrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SSIMP ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dssimp. | c %---------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c subroutine av (nx, v, w) integer nx, j, lo, n2 Double precision & v(nx*nx), w(nx*nx), one, h2 parameter ( one = 1.0D+0 ) c call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c c Scale the vector w by (1/h^2), where h is the mesh size c n2 = nx*nx h2 = one / dble((nx+1)*(nx+1)) call dscal(n2, one/h2, w, 1) return end c c------------------------------------------------------------------- subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), dd, dl, du c Double precision & one, four parameter (one = 1.0D+0, four = 4.0D+0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = four dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SIMPLE/snsimp.f000066400000000000000000000535161260666001200172600ustar00rootroot00000000000000 program snsimp c c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is a n by n real nonsymmetric matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine SNAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine SNEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-nonsym.doc in DOCUMENTS directory. c This codes implements c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (nx,x,y)" computes y = A*x c ... Use mode 1 of SNAUPD. c c\BeginLib c c\Routines called: c snaupd ARPACK reverse communication interface routine. c sneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nsimp.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv Real & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, snrm2 external slapy2, snrm2, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting mnaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 mnaitr = 0 mnapps = 0 mnaupd = 1 mnaup2 = 0 mneigh = 0 mneupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization. | c | | c | 3) This is a standard problem. | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude. | c | (indicated by which = 'LM') | c | See documentation in SNAUPD for the | c | other options SM, LR, SR, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c | | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _NSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling SNAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from SNAUPD. (see usage below) | c | | c | It MUST initially be set to 0 before the first | c | call to SNAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID). | c | | c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call snaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- Op*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c endif c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine SNEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1,) | c | | c %-------------------------------------------% c rvec = .true. c call sneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %------------------------------------------------% c | The real parts of the eigenvalues are returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part are returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first | c | NCONV (= IPARAM(5)) columns of the two | c | dimensional array V if requested. Otherwise, | c | an orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %------------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (IPARAM(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) call saxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = snrm2(n, ax, 1) call av(nx, v(1,j+1), ax) call saxpy(n, -d(j,2), v(1,j), 1, ax, 1) call saxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2( d(j,3), snrm2(n, ax, 1) ) d(j,3) = d(j,3) / slapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real, Imag) and residual residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NSIMP ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program snsimp. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c subroutine av (nx, v, w) integer nx, j, lo Real & v(nx*nx), w(nx*nx), one, h2 parameter (one = 1.0E+0) external saxpy, tv c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has complex c eigenvalues. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / real((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call saxpy(nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), h, dd, dl, du, h2 c Real & one, rho parameter (one = 1.0E+0, rho = 1.0E+2) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has complex c eigenvalues. c h = one / real(nx+1) h2 = h*h dd = 4.0E+0 / h2 dl = -one/h2 - 5.0E-1*rho/h du = -one/h2 + 5.0E-1*rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SIMPLE/sssimp.f000066400000000000000000000472011260666001200172570ustar00rootroot00000000000000 program sssimp c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is an n by n real symmetric matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine SSAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine SSEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-sym.doc in DOCUMENTS directory. c This codes implements c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x c ... Use mode 1 of SSAUPD. c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ssimp.F SID: 2.6 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, $ ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, & j, nx, ishfts, maxitr, mode1, nconv logical rvec Real & tol, sigma c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external snrm2, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting msaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 msgets = 0 msaitr = 0 msapps = 0 msaupd = 1 msaup2 = 0 mseigt = 0 mseupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in SSAUPD for the | c | other options SM, LA, SA, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 1 <= NCV <= MAXNCV | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _SSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling SSAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from SSAUPD. (See usage below.) | c | | c | It MUST initially be set to 0 before the first | c | call to SSAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID.) | c | | c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting PARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse communication loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in SSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine SSEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1.) | c | | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NCONV (=IPARAM(5)) columns of the | c | two dimensional array V if requested. | c | Otherwise, an orthogonal basis for the | c | invariant subspace corresponding to the | c | eigenvalues in D is returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SSIMP ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program sssimp. | c %---------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c subroutine av (nx, v, w) integer nx, j, lo, n2 Real & v(nx*nx), w(nx*nx), one, h2 parameter ( one = 1.0E+0 ) c call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c c Scale the vector w by (1/h^2), where h is the mesh size c n2 = nx*nx h2 = one / real((nx+1)*(nx+1)) call sscal(n2, one/h2, w, 1) return end c c------------------------------------------------------------------- subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), dd, dl, du c Real & one, four parameter (one = 1.0E+0, four = 4.0E+0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = four dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SIMPLE/znsimp.f000066400000000000000000000507411260666001200172640ustar00rootroot00000000000000 program znsimp c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is a general n by n complex matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine ZNAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine ZNEUPD . c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-complex.doc in DOCUMENTS directory. c This codes implements c c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c ... OP = A and B = I. c ... Assume "call av (nx,x,y)" computes y = A*x c ... Use mode 1 of ZNAUPD . c c\BeginLib c c\Routines called c znaupd ARPACK reverse communication interface routine. c zneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nsimp.F SID: 2.4 DATE OF SID: 10/20/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex*16 & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(2*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Double precision & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv Complex*16 & sigma Double precision & tol logical rvec c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dznrm2 , dlapy2 external dznrm2 , zaxpy , dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting mcaupd = 1 | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 mcaitr = 0 mcapps = 0 mcaupd = 1 mcaup2 = 0 mceigh = 0 mceupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = 10 n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in ZNAUPD for the | c | other options SM, LR, SR, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c | | c %-----------------------------------------------% c nev = 4 ncv = 20 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _NSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling ZNAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from ZNAUPD . (see usage below) | c | | c | It MUST initially be set to 0 before the first | c | call to ZNAUPD . | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID). | c | | c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of ZNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | ZNAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse Communication Loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% call znaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | | c | y <--- A*x | c | | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector x , and returns the resulting | c | matrix-vector product y = A*x in the | c | array workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 c endif c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine ZNEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1.) | c | | c %-------------------------------------------% c rvec = .true. c call zneupd (rvec, 'A', select, D, V, ldv, sigma, & workev, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %-----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D and the corresponding | c | eigenvectors are returned in the first | c | NCONV (=IPARAM(5)) columns of the two | c | dimensional array V if requested. Otherwise, | c | an orthogonal basis for the invariant | c | subspace corresponding to the eigenvalues in | c | D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call zaxpy (n, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble (d(j)) rd(j,2) = dimag (d(j)) rd(j,3) = dznrm2 (n, ax, 1) rd(j,3) = rd(j,3) / dlapy2 (rd(j,1),rd(j,2)) 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and relative residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NSIMP ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program znsimp . | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c subroutine av (nx, v, w) integer nx, j, lo Complex*16 & v(nx*nx), w(nx*nx), one, h2 parameter (one = (1.0D+0, 0.0D+0) ) external zaxpy c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2-dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) c on the unit squqre with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c h2 = one / dcmplx ((nx+1)*(nx+1)) c call tv(nx,v(1),w(1)) call zaxpy (nx, -one/h2, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy (nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) call zaxpy (nx, -one/h2, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy (nx, -one/h2, v(lo-nx+1), 1, w(lo+1), 1) c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex*16 & x(nx), y(nx), h, h2, dd, dl, du c Complex*16 & one, rho parameter (one = (1.0D+0, 0.0D+0) , & rho = (1.0D+2, 0.0D+0) ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / dcmplx (nx+1) h2 = h*h dd = (4.0D+0, 0.0D+0) / h2 dl = -one/h2 - (5.0D-1, 0.0D+0) *rho/h du = -one/h2 + (5.0D-1, 0.0D+0) *rho/h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SVD/000077500000000000000000000000001260666001200152315ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/SVD/Makefile.am000066400000000000000000000003171260666001200172660ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SVD = ssvd dsvd check_PROGRAMS = $(SVD) TESTS = $(check_PROGRAMS) EXTRA_DIST = README debug.h ssvd_SOURCES = ssvd.f dsvd_SOURCES = dsvd.f arpack-ng-3.3.0/EXAMPLES/SVD/README000066400000000000000000000011241260666001200161070ustar00rootroot000000000000001. Purpose ------- This directory contains simple example drivers that call ARPACK subroutine [s,d]saupd.f and [s,d]seupd.f to compute the Singular Value Decomposition of a matrix A. These drivers illustrate how to use ARPACK in considerable detail. 2. Naming Convention ----------------- The name for each driver has the form 'Xsvd.f', where X - is 's' (single precision) or 'd' (double precision) 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make ssvd". Then execute using "ssvd". arpack-ng-3.3.0/EXAMPLES/SVD/debug.h000066400000000000000000000013511260666001200164700ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/EXAMPLES/SVD/dsvd.f000066400000000000000000000526041260666001200163470ustar00rootroot00000000000000 program dsvd c c This example program is intended to illustrate the c the use of ARPACK to compute the Singular Value Decomposition. c c This code shows how to use ARPACK to find a few of the c largest singular values(sigma) and corresponding right singular c vectors (v) for the the matrix A by solving the symmetric problem: c c (A'*A)*v = sigma*v c c where A is an m by n real matrix. c c This code may be easily modified to estimate the 2-norm c condition number largest(sigma)/smallest(sigma) by setting c which = 'BE' below. This will ask for a few of the smallest c and a few of the largest singular values simultaneously. c The condition number could then be estimated by taking c the ratio of the largest and smallest singular values. c c This formulation is appropriate when m .ge. n. c Reverse the roles of A and A' in the case that m .le. n. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c largest singular values of A . c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine DSAUPD c that computes the quantities needed to construct c the desired singular values and vectors(if requested). c c 3) How to extract the desired singular values and vectors c using the ARPACK routine DSEUPD. c c 4) How to construct the left singular vectors U from the c right singular vectors V to obtain the decomposition c c A*V = U*S c c where S = diag(sigma_1, sigma_2, ..., sigma_k). c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH singular values you want to c compute and to supply a the matrix-vector products c c w <- Ax c y <- A'w c c in place of the calls to AV( ) and ATV( ) respectively below. c c Further documentation is available in the header of DSAUPD c which may be found in the SRC directory. c c This codes implements c c\Example-1 c ... Suppose we want to solve A'A*v = sigma*v in regular mode, c where A is derived from the simplest finite difference c discretization of the 2-dimensional kernel K(s,t)dt where c c K(s,t) = s(t-1) if 0 .le. s .le. t .le. 1, c t(s-1) if 0 .le. t .lt. s .le. 1. c c See subroutines AV and ATV for details. c ... OP = A'*A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x c ... Assume "call atv (n,y,w)" computes w = A'*y c ... Assume exact shifts are used c ... c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dscal Level 1 BLAS thst computes x <- x*alpha. c dcopy Level 1 BLAS thst computes y <- x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: svd.F SID: 2.4 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | It is assumed that A is M by N with M .ge. N. | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | M .le. MAXM and N .le. MAXN | c | | c | The NEV right singular vectors will be computed in | c | the N by NCV array V. | c | | c | The NEV left singular vectors will be computed in | c | the M by NEV array U. | c | | c | NEV is the number of singular values requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXM: Maximum number of rows of the A allowed. | c | MAXN: Maximum number of columns of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %------------------------------------------------------% c integer maxm, maxn, maxnev, maxncv, ldv, ldu parameter (maxm = 500, maxn=250, maxnev=10, maxncv=25, & ldu = maxm, ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), u(ldu, maxnev), & workl(maxncv*(maxncv+8)), workd(3*maxn), & s(maxncv,2), resid(maxn), ax(maxm) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, m, n, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv logical rvec Double precision & tol, sigma, temp c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external dnrm2, daxpy, dcopy, dscal c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting msaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 msgets = 0 msaitr = 0 msapps = 0 msaupd = 1 msaup2 = 0 mseigt = 0 mseupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c m = 500 n = 100 c c %------------------------------------------------% c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 singular values to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV singular values of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in DSAUPD for the | c | other options SM, BE. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %------------------------------------------------% c nev = 4 ncv = 10 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _SVD: N is greater than MAXN ' go to 9000 else if ( m .gt. maxm ) then print *, ' ERROR with _SVD: M is greater than MAXM ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SVD: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SVD: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | Specification of stopping rules and initial | c | conditions before calling DSAUPD | c | | c | abs(sigmaC - sigmaT) < TOL*abs(sigmaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from DSAUPD. (See usage below.) | c | | c | It MUST initially be set to 0 before the first | c | call to DSAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID.) | c | | c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1.) | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = n mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse communication loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %---------------------------------------% c | Perform matrix vector multiplications | c | w <--- A*x (av()) | c | y <--- A'*w (atv()) | c | The user should supply his/her own | c | matrix vector multiplication routines | c | here that takes workd(ipntr(1)) as | c | the input, and returns the result in | c | workd(ipntr(2)). | c %---------------------------------------% c call av (m, n, workd(ipntr(1)), ax) call atv (m, n, ax, workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in DSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %--------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed singular values may be extracted. | c | | c | Singular vectors may also be computed now | c | if desired. (indicated by rvec = .true.) | c | | c | The routine DSEUPD now called to do this | c | post processing | c %--------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, s, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %-----------------------------------------------% c | Singular values are returned in the first | c | column of the two dimensional array S | c | and the corresponding right singular vectors | c | are returned in the first NEV columns of the | c | two dimensional array V as requested here. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c s(j,1) = sqrt(s(j,1)) c c %-----------------------------% c | Compute the left singular | c | vectors from the formula | c | | c | u = Av/sigma | c | | c | u should have norm 1 so | c | divide by norm(Av) instead. | c %-----------------------------% c call av(m, n, v(1,j), ax) call dcopy(m, ax, 1, u(1,j), 1) temp = one/dnrm2(m, u(1,j), 1) call dscal(m, temp, u(1,j), 1) c c %---------------------------% c | | c | Compute the residual norm | c | | c | || A*v - sigma*u || | c | | c | for the NCONV accurately | c | computed singular values | c | and vectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance). | c | Store the result in 2nd | c | column of array S. | c %---------------------------% c call daxpy(m, -s(j,1), u(1,j), 1, ax, 1) s(j,2) = dnrm2(m, ax, 1) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call dmout(6, nconv, 2, s, maxncv, -6, & 'Singular values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SVD ' print *, ' ==== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %-------------------------% c | Done with program dsvd. | c %-------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutines c c The matrix A is derived from the simplest finite difference c discretization of the integral operator c c f(s) = integral(K(s,t)x(t)dt). c c Thus, the matrix A is a discretization of the 2-dimensional kernel c K(s,t)dt, where c c K(s,t) = s(t-1) if 0 .le. s .le. t .le. 1, c t(s-1) if 0 .le. t .lt. s .le. 1. c c Thus A is an m by n matrix with entries c c A(i,j) = k*(si)*(tj - 1) if i .le. j, c k*(tj)*(si - 1) if i .gt. j c c where si = i/(m+1) and tj = j/(n+1) and k = 1/(n+1). c c------------------------------------------------------------------- c subroutine av (m, n, x, w) c c computes w <- A*x c integer m, n, i, j Double precision & x(n), w(m), one, zero, h, k, s, t parameter ( one = 1.0D+0, zero = 0.0D+0 ) c h = one / dble(m+1) k = one / dble(n+1) do 5 i = 1,m w(i) = zero 5 continue t = zero c do 30 j = 1,n t = t+k s = zero do 10 i = 1,j s = s+h w(i) = w(i) + k*s*(t-one)*x(j) 10 continue do 20 i = j+1,m s = s+h w(i) = w(i) + k*t*(s-one)*x(j) 20 continue 30 continue c return end c c------------------------------------------------------------------- c subroutine atv (m, n, w, y) c c computes y <- A'*w c integer m, n, i, j Double precision & w(m), y(n), one, zero, h, k, s, t parameter ( one = 1.0D+0, zero = 0.0D+0 ) c h = one / dble(m+1) k = one / dble(n+1) do 5 i = 1,n y(i) = zero 5 continue t = zero c do 30 j = 1,n t = t+k s = zero do 10 i = 1,j s = s+h y(j) = y(j) + k*s*(t-one)*w(i) 10 continue do 20 i = j+1,m s = s+h y(j) = y(j) + k*t*(s-one)*w(i) 20 continue 30 continue c return end c arpack-ng-3.3.0/EXAMPLES/SVD/ssvd.f000066400000000000000000000524741260666001200163730ustar00rootroot00000000000000 program ssvd c c This example program is intended to illustrate the c the use of ARPACK to compute the Singular Value Decomposition. c c This code shows how to use ARPACK to find a few of the c largest singular values(sigma) and corresponding right singular c vectors (v) for the the matrix A by solving the symmetric problem: c c (A'*A)*v = sigma*v c c where A is an m by n real matrix. c c This code may be easily modified to estimate the 2-norm c condition number largest(sigma)/smallest(sigma) by setting c which = 'BE' below. This will ask for a few of the smallest c and a few of the largest singular values simultaneously. c The condition number could then be estimated by taking c the ratio of the largest and smallest singular values. c c This formulation is appropriate when m .ge. n. c Reverse the roles of A and A' in the case that m .le. n. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c largest singular values of A . c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine SSAUPD c that computes the quantities needed to construct c the desired singular values and vectors(if requested). c c 3) How to extract the desired singular values and vectors c using the ARPACK routine SSEUPD. c c 4) How to construct the left singular vectors U from the c right singular vectors V to obtain the decomposition c c A*V = U*S c c where S = diag(sigma_1, sigma_2, ..., sigma_k). c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH singular values you want to c compute and to supply a the matrix-vector products c c w <- Ax c y <- A'w c c in place of the calls to AV( ) and ATV( ) respectively below. c c Further documentation is available in the header of DSAUPD c which may be found in the SRC directory. c c This codes implements c c\Example-1 c ... Suppose we want to solve A'A*v = sigma*v in regular mode, c where A is derived from the simplest finite difference c discretization of the 2-dimensional kernel K(s,t)dt where c c K(s,t) = s(t-1) if 0 .le. s .le. t .le. 1, c t(s-1) if 0 .le. t .lt. s .le. 1. c c See subroutines AV and ATV for details. c ... OP = A'*A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x c ... Assume "call atv (n,y,w)" computes w = A'*y c ... Assume exact shifts are used c ... c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c sscal Level 1 BLAS thst computes x <- x*alpha. c scopy Level 1 BLAS thst computes y <- x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: svd.F SID: 2.4 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | It is assumed that A is M by N with M .ge. N. | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | M .le. MAXM and N .le. MAXN | c | | c | The NEV right singular vectors will be computed in | c | the N by NCV array V. | c | | c | The NEV left singular vectors will be computed in | c | the M by NEV array U. | c | | c | NEV is the number of singular values requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXM: Maximum number of rows of the A allowed. | c | MAXN: Maximum number of columns of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %------------------------------------------------------% c integer maxm, maxn, maxnev, maxncv, ldv, ldu parameter (maxm = 500, maxn=250, maxnev=10, maxncv=25, & ldu = maxm, ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), u(ldu, maxnev), & workl(maxncv*(maxncv+8)), workd(3*maxn), & s(maxncv,2), resid(maxn), ax(maxm) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, m, n, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv logical rvec Real & tol, sigma, temp c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external snrm2, saxpy, scopy, sscal c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting msaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 msgets = 0 msaitr = 0 msapps = 0 msaupd = 1 msaup2 = 0 mseigt = 0 mseupd = 0 c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c m = 500 n = 100 c c %------------------------------------------------% c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 singular values to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization | c | | c | 3) This is a standard problem | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV singular values of | c | largest magnitude | c | (indicated by which = 'LM') | c | See documentation in SSAUPD for the | c | other options SM, BE. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %------------------------------------------------% c nev = 4 ncv = 10 bmat = 'I' which = 'LM' c if ( n .gt. maxn ) then print *, ' ERROR with _SVD: N is greater than MAXN ' go to 9000 else if ( m .gt. maxm ) then print *, ' ERROR with _SVD: M is greater than MAXM ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SVD: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SVD: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | Specification of stopping rules and initial | c | conditions before calling SSAUPD | c | | c | abs(sigmaC - sigmaT) < TOL*abs(sigmaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from SSAUPD. (See usage below.) | c | | c | It MUST initially be set to 0 before the first | c | call to SSAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID.) | c | | c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1.) | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SSAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = n mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %------------------------------------------------% c | M A I N L O O P (Reverse communication loop) | c %------------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %---------------------------------------% c | Perform matrix vector multiplications | c | w <--- A*x (av()) | c | y <--- A'*w (atv()) | c | The user should supply his/her own | c | matrix vector multiplication routines | c | here that takes workd(ipntr(1)) as | c | the input, and returns the result in | c | workd(ipntr(2)). | c %---------------------------------------% c call av (m, n, workd(ipntr(1)), ax) call atv (m, n, ax, workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in SSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %--------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed singular values may be extracted. | c | | c | Singular vectors may also be computed now | c | if desired. (indicated by rvec = .true.) | c | | c | The routine SSEUPD now called to do this | c | post processing | c %--------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, s, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %-----------------------------------------------% c | Singular values are returned in the first | c | column of the two dimensional array S | c | and the corresponding right singular vectors | c | are returned in the first NEV columns of the | c | two dimensional array V as requested here. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c s(j,1) = sqrt(s(j,1)) c c %-----------------------------% c | Compute the left singular | c | vectors from the formula | c | | c | u = Av/sigma | c | | c | u should have norm 1 so | c | divide by norm(Av) instead. | c %-----------------------------% c call av(m, n, v(1,j), ax) call scopy(m, ax, 1, u(1,j), 1) temp = one/snrm2(m, u(1,j), 1) call sscal(m, temp, u(1,j), 1) c c %---------------------------% c | | c | Compute the residual norm | c | | c | || A*v - sigma*u || | c | | c | for the NCONV accurately | c | computed singular values | c | and vectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance). | c | Store the result in 2nd | c | column of array S. | c %---------------------------% c call saxpy(m, -s(j,1), u(1,j), 1, ax, 1) s(j,2) = snrm2(m, ax, 1) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call smout(6, nconv, 2, s, maxncv, -6, & 'Singular values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SVD ' print *, ' ==== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %-------------------------% c | Done with program ssvd. | c %-------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutines c c The matrix A is derived from the simplest finite difference c discretization of the integral operator c c f(s) = integral(K(s,t)x(t)dt). c c Thus, the matrix A is a discretization of the 2-dimensional kernel c K(s,t)dt, where c c K(s,t) = s(t-1) if 0 .le. s .le. t .le. 1, c t(s-1) if 0 .le. t .lt. s .le. 1. c c Thus A is an m by n matrix with entries c c A(i,j) = k*(si)*(tj - 1) if i .le. j, c k*(tj)*(si - 1) if i .gt. j c c where si = i/(m+1) and tj = j/(n+1) and k = 1/(n+1). c c------------------------------------------------------------------- c subroutine av (m, n, x, w) c c computes w <- A*x c integer m, n, i, j Real & x(n), w(m), one, zero, h, k, s, t parameter ( one = 1.0E+0, zero = 0.0E+0 ) c h = one / real(m+1) k = one / real(n+1) do 5 i = 1,m w(i) = zero 5 continue t = zero c do 30 j = 1,n t = t+k s = zero do 10 i = 1,j s = s+h w(i) = w(i) + k*s*(t-one)*x(j) 10 continue do 20 i = j+1,m s = s+h w(i) = w(i) + k*t*(s-one)*x(j) 20 continue 30 continue c return end c c------------------------------------------------------------------- c subroutine atv (m, n, w, y) c c computes y <- A'*w c integer m, n, i, j Real & w(m), y(n), one, zero, h, k, s, t parameter ( one = 1.0E+0, zero = 0.0E+0 ) c h = one / real(m+1) k = one / real(n+1) do 5 i = 1,n y(i) = zero 5 continue t = zero c do 30 j = 1,n t = t+k s = zero do 10 i = 1,j s = s+h y(j) = y(j) + k*s*(t-one)*w(i) 10 continue do 20 i = j+1,m s = s+h y(j) = y(j) + k*t*(s-one)*w(i) 20 continue 30 continue c return end c arpack-ng-3.3.0/EXAMPLES/SYM/000077500000000000000000000000001260666001200152455ustar00rootroot00000000000000arpack-ng-3.3.0/EXAMPLES/SYM/Makefile.am000066400000000000000000000012441260666001200173020ustar00rootroot00000000000000LDADD = $(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SSDRV = ssdrv1 ssdrv2 ssdrv3 ssdrv4 ssdrv5 ssdrv6 DSDRV = dsdrv1 dsdrv2 dsdrv3 dsdrv4 dsdrv5 dsdrv6 SYM = $(SSDRV) $(DSDRV) check_PROGRAMS = $(SYM) TESTS = $(check_PROGRAMS) EXTRA_DIST = README # simple symmetric problem using single precision ssdrv1_SOURCES = ssdrv1.f ssdrv2_SOURCES = ssdrv2.f ssdrv3_SOURCES = ssdrv3.f ssdrv4_SOURCES = ssdrv4.f ssdrv5_SOURCES = ssdrv5.f ssdrv6_SOURCES = ssdrv6.f # simple symmetric problem using double precision dsdrv1_SOURCES = dsdrv1.f dsdrv2_SOURCES = dsdrv2.f dsdrv3_SOURCES = dsdrv3.f dsdrv4_SOURCES = dsdrv4.f dsdrv5_SOURCES = dsdrv5.f dsdrv6_SOURCES = dsdrv6.f arpack-ng-3.3.0/EXAMPLES/SYM/README000066400000000000000000000041351260666001200161300ustar00rootroot000000000000001. Purpose ------- This directory contains example drivers that call ARPACK subroutines [s,d]saupd.f and [s,d]seupd.f to solve SYMMETRIC eigenvalue problems using regular, inverse, shift-invert or other special modes (such as Cayley, Bucking etc.) These drivers illustrate how to set various ARPACK parameters to solve different problems in different modes. They provide a guideline on how to use ARPACK's reverse communication interface. The user may modify any one of these drivers, and provide his/her own matrix vector multiplication routine to solve the problem of his/her own interest. 2. Naming convention ----------------- The name for each driver has the form 'XsdrvN.f', where X - is 's' (single precision) or 'd' (double precision) N - is a number between 1 and 6. If N = 1, the driver solves a STANDARD eigenvalue problem in REGULAR mode N = 2, the driver solves a STANDARD eigenvalue problem in SHIFT-INVERT mode. N = 3, the driver solves a GENERALIZED eigenvalue problem in INVERSE mode N = 4, the driver solves a GENERALIZED eigenvalue problem in SHIFT-INVERT mode. These are 4 commonly used drivers. For shift-invert (N=2,4) mode the user needs to supply a linear system solver to perform y=inv[A-sigma*B]*x. When N > 4, a special mode is used. If N = 5, the driver solves a GENERALIZED eigenvalue problem in BUCKLING mode. N = 6, the driver solves a GENERALIZED eigenvalue problem in CAYLEY mode. These two drivers require the user to provide linear system solvers also. For more information on Cayley and Buckling mode, see the following reference: R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", SIAM J. Matr. Anal. Apps., January (1993). 3. Usage ----- To run these drivers, you may use the makefile in this directory and issue, for example, "make ssdrv1". Then execute using "ssdrv1". arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv1.f000066400000000000000000000342071260666001200166250ustar00rootroot00000000000000 program dsdrv1 c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square [0,1]x[0,1] c with zero Dirichlet boundary condition. c c ... OP = A and B = I. c c ... Assume "call av (n,x,y)" computes y = A*x. c c ... Use mode 1 of DSAUPD. c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv1.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, $ ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Double precision & tol, sigma c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external dnrm2, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in DSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = dnrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV1 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv1. | c %---------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c subroutine av (nx, v, w) integer nx, j, lo, n2 Double precision & v(nx*nx), w(nx*nx), one, h2 parameter ( one = 1.0D+0 ) c call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c c Scale the vector w by (1/h^2), where h is the mesh size c n2 = nx*nx h2 = one / dble((nx+1)*(nx+1)) call dscal(n2, one/h2, w, 1) return end c c------------------------------------------------------------------- subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), dd, dl, du c Double precision & one parameter (one = 1.0D+0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0D+0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv2.f000066400000000000000000000333001260666001200166170ustar00rootroot00000000000000 program dsdrv2 c c Program to illustrate the idea of reverse communication c in shift and invert mode for a standard symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c dgttrf.f and dgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example two of ex-sym.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the central difference discretization c of the 1-dimensional Laplacian on [0,1] with zero Dirichlet c boundary condition. c ... OP = (inv[A - sigma*I]) and B = I. c ... Use mode 3 of DSAUPD. c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv2.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & sigma, tol, h2 c c %------------% c | Parameters | c %------------% c Double precision & zero, one, two parameter (zero = 0.0D+0, one = 1.0D+0, & two = 2.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy, dnrm2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = 'I'. | c | NEV is the number of eigenvalues (closest to | c | SIGMA) to be approximated. Since the shift-invert | c | mode is used, WHICH is set to 'LM'. The user can | c | modify NEV, NCV, SIGMA to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV2: NCV is greater than MAXNCV ' go to 9000 end if c bmat = 'I' which = 'LM' sigma = zero c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DSAUPD is used | c | (IPARAM(7) = 3). All these options may be | c | changed by the user. For details, see the | c | documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-----------------------------------------------------% c | Call LAPACK routine to factor (A-SIGMA*I), where A | c | is the 1-d Laplacian. | c %-----------------------------------------------------% c h2 = one / dble((n+1)*(n+1)) do 20 j=1,n ad(j) = two / h2 - sigma adl(j) = -one / h2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in SDRV2.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*I]*x. | c | The user only need the linear system | c | solver here that takes workd(ipntr(1)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %----------------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) c call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV2. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %----------------------------% c | Error message. Check the | c | documentation in DSAUPD | c %----------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = dnrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV2 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1 dimensional discrete Laplacian on c the interval [0,1] with zero Dirichlet boundary condition. c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, h2 parameter (one = 1.0D+0, two = 2.0D+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1 / h^2). c h2 = one / dble((n+1)*(n+1)) call dscal(n, one/h2, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv3.f000066400000000000000000000375271260666001200166370ustar00rootroot00000000000000 program dsdrv3 c c Program to illustrate the idea of reverse communication in c inverse mode for a generalized symmetric eigenvalue problem. c The following program uses the two LAPACK subroutines dgttrf .f c and dgttrs .f to factor and solve a tridiagonal system of equations. c c We implement example three of ex-sym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = inv[M]*A and B = M. c c ... Use mode 2 of DSAUPD . c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dscal Level 1 BLAS that scales a vector by a scalar. c dcopy Level 1 BLAS that copies one vector to another. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv3.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Double precision & zero, one, four, six parameter ( zero = 0.0D+0 , one = 1.0D+0 , & four = 4.0D+0 , six = 6.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy , dcopy , dscal , dnrm2 , dgttrf , dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DSAUPD is used | c | (IPARAM(7) = 2). All these options may be | c | changed by the user. For details, see the | c | documentation in DSAUPD . | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------% c | Call LAPACK routine to factor the mass matrix. | c | The mass matrix is the tridiagonal matrix | c | arising from using piecewise linear finite | c | elements on the interval [0, 1]. | c %------------------------------------------------% c h = one / dble (n+1) c r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = r1 adl(j) = r2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV3. ' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x. | c | The user should supply his/her own | c | matrix vector multiplication (A*x) | c | routine and a linear system solver | c | here. The matrix vector | c | multiplication routine takes | c | workd(ipntr(1)) as the input vector. | c | The final result is returned to | c | workd(ipntr(2)). The result of A*x | c | overwrites workd(ipntr(1)). | c %--------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call dcopy (n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV3.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %-----------------------------------------% c | Perform y <--- M*x. | c | Need the matrix vector multiplication | c | routine here that takes workd(ipntr(1)) | c | as the input and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD . | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if (ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD . | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2 (n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout (6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV3 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv3 . | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1 dimensional mass matrix c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Double precision & v(n),w(n), one, four, six, h parameter (one = 1.0D+0 , four = 4.0D+0 , & six = 6.0D+0 ) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (dble (n+1)*six) call dscal (n, h, w, 1) return end c c-------------------------------------------------------------------- c matrix vector subroutine c c The matrix used is the stiffness matrix obtained from the finite c element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition using c piecewise linear elements. c subroutine av (n, v, w) integer n, j Double precision & v(n),w(n), two, one, h parameter ( one = 1.0D+0 , two = 2.0D+0 ) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1 / h). c h = one / dble (n+1) call dscal (n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv4.f000066400000000000000000000414661260666001200166350ustar00rootroot00000000000000 program dsdrv4 c c Program to illustrate the idea of reverse communication c in shift and invert mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c dgttrf.f and dgttrs to factor and solve a tridiagonal system of c equations. c c We implement example four of ex-sym.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained from the finite element discretrization c of the 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = (inv[A - sigma*M])*M and B = M. c c ... Use mode 3 of DSAUPD. c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector by a scalar. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Double precision & zero, one, two, four, six parameter (zero = 0.0D+0, one = 1.0D+0, & four = 4.0D+0, six = 6.0D+0, & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy, dcopy, dscal, dnrm2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues (closest to | c | the shift SIGMA) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMA to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 specified in the | c | documentation of DSAUPD is used (IPARAM(7) = 3). | c | All these options may be changed by the user. | c | For details, see the documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------------------% c | Call LAPACK routine to factor the tridiagonal matrix | c | (A-SIGMA*M). The matrix A is the 1-d discrete | c | Laplacian. The matrix M is the associated mass matrix | c | arising from using piecewise linear finite elements | c | on the interval [0, 1]. | c %-------------------------------------------------------% c h = one / dble(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two/h - sigma * r1 adl(j) = -one/h - sigma * r2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' Error with _gttrf in _SDRV4.' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1) then c c %--------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force the starting vector into the | c | range of OP. The user should supply | c | his/her own matrix vector multiplication | c | routine and a linear system solver here. | c | The matrix vector multiplication routine | c | takes workd(ipntr(1)) as the input vector. | c | The final result is returned to | c | workd(ipntr(2)). | c %--------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV4. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | the user only needs the linear system | c | solver here that takes workd(ipntr(3) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call dcopy ( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV4.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %-----------------------------------------% c | Perform y <--- M*x | c | Need the matrix vector multiplication | c | routine here that takes workd(ipntr(1)) | c | as the input and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), workd) call mv(n, v(1,j), workd(n+1)) call daxpy (n, -d(j,1), workd(n+1), 1, workd, 1) d(j,2) = dnrm2(n, workd, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV4 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv4. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c matrix vector subroutine c The matrix used is the 1 dimensional mass matrix c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Double precision & v(n),w(n), one, four, six, h parameter (one = 1.0D+0, four = 4.0D+0, & six = 6.0D+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / ( six*dble(n+1)) call dscal(n, h, w, 1) return end c------------------------------------------------------------------------ c matrix vector subroutine c where the matrix is the finite element discretization of the c 1 dimensional discrete Laplacian on [0,1] with zero Dirichlet c boundary condition using piecewise linear elements. c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), two, one, h parameter (one = 1.0D+0, two = 2.0D+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h) c h = one / dble(n+1) call dscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv5.f000066400000000000000000000412501260666001200166250ustar00rootroot00000000000000 program dsdrv5 c c Program to illustrate the idea of reverse communication c in Buckling mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c dgttrf.f and dgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example five of ex-sym.doc in DOCUMENTS directory c c\Example-5 c ... Suppose we want to solve K*x = lambda*KG*x in Buckling mode c where K and KG are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c ... OP = (inv[K - sigma*KG])*K and B = K. c ... Use mode 4 of DSAUPD. c c\BeginLib c c\References: c 1. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector by a scalar. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv5.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & h, sigma, r1, r2, tol c c %------------% c | Parameters | c %------------% c Double precision & zero, one, two, four, six parameter (zero = 0.0D+0, one = 1.0D+0, & four = 4.0D+0, six = 6.0D+0, & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy, dcopy, dscal, dnrm2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. Since the buckling mode is used, | c | WHICH is set to 'LM'. The user can modify NEV, | c | NCV, SIGMA to solve problems of different sizes, | c | and to get different parts of the spectrum. | c | However, The following conditions must be | c | satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c | | c | The shift SIGMA cannot be zero!!! | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = one c c %-----------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 specified in the | c | documentation of DSAUPD is used (IPARAM(7) = 4). | c | All these options may be changed by the user. For | c | details, see the documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 4 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------------% c | Call LAPACK routine to factor the tridiagonal matrix | c | (K-SIGMA*KG). The matrix A is the 1-d discrete | c | Laplacian on the interval [0,1] with zero Dirichlet | c | boundary condition. The matrix M is the associated | c | mass matrix arising from using piecewise linear | c | finite elements on the interval [0, 1]. | c %------------------------------------------------------% c h = one / dble(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two / h - sigma * r1 adl(j) = -one / h- sigma * r2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV5.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[K-SIGMA*KG]*K*x | c | to force starting vector into the range | c | of OP. The user should provide his/her | c | matrix vector multiplication routine and | c | a linear system solver here. The matrix | c | vector multiplication routine (K*x) takes | c | workd(ipntr(1)) as the input vector. The | c | final result is returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) c call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in SDRV5.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %------------------------------------------% c | Perform y <-- OP*x=inv(K-sigma*KG)*K*x. | c | K*x has been saved in workd(ipntr(3)). | c | The user only needs the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %------------------------------------------% c call dcopy ( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV5.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- K*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) c c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c if (ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ',ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV5 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is', n print *, ' The number of Ritz values requested is', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv5. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1-dimensional mass matrix c arising from using piecewise linear finite elements on the c interval [0,1]. c subroutine mv (n, v, w) integer n, j Double precision & v(n),w(n), one, four, six, h parameter (one = 1.0D+0, four = 4.0D+0, & six = 6.0D+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (six*dble(n+1)) call dscal(n, h, w, 1) return end c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the stiffness matrix obtained from the c finite element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, h parameter (one = 1.0D+0, two = 2.0D+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h) c h = one / (n+1) call dscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/dsdrv6.f000066400000000000000000000430571260666001200166350ustar00rootroot00000000000000 program dsdrv6 c c Program to illustrate the idea of reverse communication c in Cayley mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c dgttrf.f and dgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example six of ex-sym.doc in DOCUMENTS directory c c\Example-6 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = (inv[A-sigma*M])*(A+sigma*M) and B = M. c c ... Use mode 5 of DSAUPD. c c\BeginLib c c\References: c 1. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector by a scalar. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv6.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------ c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & temp(maxn), ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Double precision & zero, one, two, four, six parameter (zero = 0.0D+0, one = 1.0D+0, & four = 4.0D+0, six = 6.0D+0, & two = 2.0D+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy, dcopy, dscal, dnrm2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. Since the Cayley mode is used, | c | WHICH is set to 'LM'. The user can modify NEV, | c | NCV, SIGMA to solve problems of different sizes, | c | and to get different parts of the spectrum. | c | However, The following conditions must be | c | satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 1.5D+2 c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 5 specified in the | c | documentation of DSAUPD is used (IPARAM(7) = 5). | c | All these options may be changed by the user. For | c | details, see the documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 5 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------------% c | Call LAPACK routine to factor (A-sigma*M). The | c | stiffness matrix A is the 1-d discrete Laplacian. | c | The mass matrix M is the associated mass matrix | c | arising from using piecewise linear finite elements | c | on the interval [0, 1]. | c %------------------------------------------------------% c h = one / dble(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two / h - sigma * r1 adl(j) = -one / h - sigma * r2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV6.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c c %-------------------------------------------------------% c | Perform y <--- OP*x = (inv[A-SIGMA*M])*(A+SIGMA*M)*x | c | to force starting vector into the range of OP. The | c | user should provide his/her matrix vector (A*x, M*x) | c | multiplication routines and a linear system solver | c | here. The matrix vector multiplication routine takes | c | workd(ipntr(1)) as the input vector. The final | c | result is returned to workd(ipntr(2)). | c %-------------------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call mv (n, workd(ipntr(1)), temp) call daxpy(n, sigma, temp, 1, workd(ipntr(2)), 1) c call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV6.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %----------------------------------------------------% c | Perform y <-- OP*x = inv[A-SIGMA*M]*(A+SIGMA*M)*x. | c | M*x has been saved in workd(ipntr(3)). The user | c | need the matrix vector multiplication (A*x) | c | routine and a linear system solver here. The | c | matrix vector multiplication routine takes | c | workd(ipntr(1)) as the input, and the result is | c | combined with workd(ipntr(3)) to form the input | c | for the linear system solver. The final result is | c | returned to workd(ipntr(2)). | c %----------------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call daxpy(n, sigma, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV6. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %--------------------------------------------% c | Perform y <--- M*x. | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %--------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd. ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call dseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c nconv = iparam(5) do 30 j=1, nconv call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call daxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = dnrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) 30 continue c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV6 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is', n print *, ' The number of Ritz values requested is', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv6. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix used is the 1 dimensional mass matrix c arising from using the piecewise linear finite element c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Double precision & v(n), w(n), one, four, six, h parameter (one = 1.0D+0, four = 4.0D+0, & six = 6.0D+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (six*dble(n+1)) call dscal(n, h, w, 1) return end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the stiffness matrix obtained from the c finite element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, h parameter (one = 1.0D+0, two = 2.0D+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h). c h = one / dble(n+1) call dscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv1.f000066400000000000000000000340631260666001200166440ustar00rootroot00000000000000 program ssdrv1 c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square [0,1]x[0,1] c with zero Dirichlet boundary condition. c c ... OP = A and B = I. c c ... Assume "call av (n,x,y)" computes y = A*x. c c ... Use mode 1 of SSAUPD. c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv1.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, $ ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Real & tol, sigma c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external snrm2, saxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV1: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of SSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av (nx, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in SSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(nx, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV1 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv1. | c %---------------------------% c 9000 continue c end c c ------------------------------------------------------------------ c matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c subroutine av (nx, v, w) integer nx, j, lo, n2 Real & v(nx*nx), w(nx*nx), one, h2 parameter ( one = 1.0E+0 ) c call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, nx-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (nx-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c c Scale the vector w by (1/h^2), where h is the mesh size c n2 = nx*nx h2 = one / real((nx+1)*(nx+1)) call sscal(n2, one/h2, w, 1) return end c c------------------------------------------------------------------- subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), dd, dl, du c Real & one parameter (one = 1.0E+0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0E+0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv2.f000066400000000000000000000332041260666001200166410ustar00rootroot00000000000000 program ssdrv2 c c Program to illustrate the idea of reverse communication c in shift and invert mode for a standard symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c sgttrf.f and sgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example two of ex-sym.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the central difference discretization c of the 1-dimensional Laplacian on [0,1] with zero Dirichlet c boundary condition. c ... OP = (inv[A - sigma*I]) and B = I. c ... Use mode 3 of SSAUPD. c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c saxpy saxpy Level 1 BLAS that computes y <- alpha*x+y. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv2.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Real & sigma, tol, h2 c c %------------% c | Parameters | c %------------% c Real & zero, one, two parameter (zero = 0.0E+0, one = 1.0E+0, & two = 2.0E+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external saxpy, snrm2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = 'I'. | c | NEV is the number of eigenvalues (closest to | c | SIGMA) to be approximated. Since the shift-invert | c | mode is used, WHICH is set to 'LM'. The user can | c | modify NEV, NCV, SIGMA to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV2: NCV is greater than MAXNCV ' go to 9000 end if c bmat = 'I' which = 'LM' sigma = zero c c %--------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of SSAUPD is used | c | (IPARAM(7) = 3). All these options may be | c | changed by the user. For details, see the | c | documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-----------------------------------------------------% c | Call LAPACK routine to factor (A-SIGMA*I), where A | c | is the 1-d Laplacian. | c %-----------------------------------------------------% c h2 = one / real((n+1)*(n+1)) do 20 j=1,n ad(j) = two / h2 - sigma adl(j) = -one / h2 20 continue call scopy (n, adl, 1, adu, 1) call sgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in SDRV2.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*I]*x. | c | The user only need the linear system | c | solver here that takes workd(ipntr(1)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %----------------------------------------% c call scopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) c call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV2. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %----------------------------% c | Error message. Check the | c | documentation in SSAUPD | c %----------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call saxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV2 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1 dimensional discrete Laplacian on c the interval [0,1] with zero Dirichlet boundary condition. c subroutine av (n, v, w) integer n, j Real & v(n), w(n), one, two, h2 parameter (one = 1.0E+0, two = 2.0E+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1 / h^2). c h2 = one / real((n+1)*(n+1)) call sscal(n, one/h2, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv3.f000066400000000000000000000373461260666001200166550ustar00rootroot00000000000000 program ssdrv3 c c Program to illustrate the idea of reverse communication in c inverse mode for a generalized symmetric eigenvalue problem. c The following program uses the two LAPACK subroutines sgttrf.f c and sgttrs.f to factor and solve a tridiagonal system of equations. c c We implement example three of ex-sym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = inv[M]*A and B = M. c c ... Use mode 2 of SSAUPD. c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c sscal Level 1 BLAS that scales a vector by a scalar. c scopy Level 1 BLAS that copies one vector to another. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv3.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Real & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Real & zero, one, four, six parameter ( zero = 0.0E+0 , one = 1.0E+0 , & four = 4.0E+0 , six = 6.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external saxpy, scopy, sscal, snrm2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV3: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %--------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SSAUPD is used | c | (IPARAM(7) = 2). All these options may be | c | changed by the user. For details, see the | c | documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------% c | Call LAPACK routine to factor the mass matrix. | c | The mass matrix is the tridiagonal matrix | c | arising from using piecewise linear finite | c | elements on the interval [0, 1]. | c %------------------------------------------------% c h = one / real (n+1) c r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = r1 adl(j) = r2 20 continue call scopy (n, adl, 1, adu, 1) call sgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV3. ' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x. | c | The user should supply his/her own | c | matrix vector multiplication (A*x) | c | routine and a linear system solver | c | here. The matrix vector | c | multiplication routine takes | c | workd(ipntr(1)) as the input vector. | c | The final result is returned to | c | workd(ipntr(2)). The result of A*x | c | overwrites workd(ipntr(1)). | c %--------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call scopy(n, workd(ipntr(2)), 1, workd(ipntr(1)), 1) call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV3.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %-----------------------------------------% c | Perform y <--- M*x. | c | Need the matrix vector multiplication | c | routine here that takes workd(ipntr(1)) | c | as the input and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if (ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy(n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV3 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv3. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1 dimensional mass matrix c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Real & v(n),w(n), one, four, six, h parameter (one = 1.0E+0 , four = 4.0E+0 , & six = 6.0E+0 ) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (real (n+1)*six) call sscal(n, h, w, 1) return end c c-------------------------------------------------------------------- c matrix vector subroutine c c The matrix used is the stiffness matrix obtained from the finite c element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition using c piecewise linear elements. c subroutine av (n, v, w) integer n, j Real & v(n),w(n), two, one, h parameter ( one = 1.0E+0 , two = 2.0E+0 ) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1 / h). c h = one / real (n+1) call sscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv4.f000066400000000000000000000413561260666001200166520ustar00rootroot00000000000000 program ssdrv4 c c Program to illustrate the idea of reverse communication c in shift and invert mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c sgttrf.f and sgttrs to factor and solve a tridiagonal system of c equations. c c We implement example four of ex-sym.doc in DOCUMENTS directory c c\Example-4 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained from the finite element discretrization c of the 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = (inv[A - sigma*M])*M and B = M. c c ... Use mode 3 of SSAUPD. c c\BeginLib c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector by a scalar. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv4.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Real & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Real & zero, one, two, four, six parameter (zero = 0.0E+0, one = 1.0E+0, & four = 4.0E+0, six = 6.0E+0, & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external saxpy, scopy, sscal, snrm2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues (closest to | c | the shift SIGMA) to be approximated. Since the | c | shift-invert mode is used, WHICH is set to 'LM'. | c | The user can modify NEV, NCV, SIGMA to solve | c | problems of different sizes, and to get different | c | parts of the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV4: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV4: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV4: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = zero c c %--------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 specified in the | c | documentation of SSAUPD is used (IPARAM(7) = 3). | c | All these options may be changed by the user. | c | For details, see the documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------------------% c | Call LAPACK routine to factor the tridiagonal matrix | c | (A-SIGMA*M). The matrix A is the 1-d discrete | c | Laplacian. The matrix M is the associated mass matrix | c | arising from using piecewise linear finite elements | c | on the interval [0, 1]. | c %-------------------------------------------------------% c h = one / real(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two/h - sigma * r1 adl(j) = -one/h - sigma * r2 20 continue call scopy (n, adl, 1, adu, 1) call sgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' Error with _gttrf in _SDRV4.' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1) then c c %--------------------------------------------% c | Perform y <--- OP*x = inv[A-SIGMA*M]*M*x | c | to force the starting vector into the | c | range of OP. The user should supply | c | his/her own matrix vector multiplication | c | routine and a linear system solver here. | c | The matrix vector multiplication routine | c | takes workd(ipntr(1)) as the input vector. | c | The final result is returned to | c | workd(ipntr(2)). | c %--------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV4. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %-----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*M]*M*x | c | M*x has been saved in workd(ipntr(3)). | c | the user only needs the linear system | c | solver here that takes workd(ipntr(3) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call scopy ( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV4.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %-----------------------------------------% c | Perform y <--- M*x | c | Need the matrix vector multiplication | c | routine here that takes workd(ipntr(1)) | c | as the input and returns the result to | c | workd(ipntr(2)). | c %-----------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), workd) call mv(n, v(1,j), workd(n+1)) call saxpy (n, -d(j,1), workd(n+1), 1, workd, 1) d(j,2) = snrm2(n, workd, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV4 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv4. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c matrix vector subroutine c The matrix used is the 1 dimensional mass matrix c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Real & v(n),w(n), one, four, six, h parameter (one = 1.0E+0, four = 4.0E+0, & six = 6.0E+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / ( six*real(n+1)) call sscal(n, h, w, 1) return end c------------------------------------------------------------------------ c matrix vector subroutine c where the matrix is the finite element discretization of the c 1 dimensional discrete Laplacian on [0,1] with zero Dirichlet c boundary condition using piecewise linear elements. c subroutine av (n, v, w) integer n, j Real & v(n), w(n), two, one, h parameter (one = 1.0E+0, two = 2.0E+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h) c h = one / real(n+1) call sscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv5.f000066400000000000000000000411401260666001200166420ustar00rootroot00000000000000 program ssdrv5 c c Program to illustrate the idea of reverse communication c in Buckling mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c sgttrf.f and sgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example five of ex-sym.doc in DOCUMENTS directory c c\Example-5 c ... Suppose we want to solve K*x = lambda*KG*x in Buckling mode c where K and KG are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c ... OP = (inv[K - sigma*KG])*K and B = K. c ... Use mode 4 of SSAUPD. c c\BeginLib c c\References: c 1. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector by a scalar. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv5.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Real & h, sigma, r1, r2, tol c c %------------% c | Parameters | c %------------% c Real & zero, one, two, four, six parameter (zero = 0.0E+0, one = 1.0E+0, & four = 4.0E+0, six = 6.0E+0, & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external saxpy, scopy, sscal, snrm2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. Since the buckling mode is used, | c | WHICH is set to 'LM'. The user can modify NEV, | c | NCV, SIGMA to solve problems of different sizes, | c | and to get different parts of the spectrum. | c | However, The following conditions must be | c | satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c | | c | The shift SIGMA cannot be zero!!! | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV5: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV5: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV5: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = one c c %-----------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 4 specified in the | c | documentation of SSAUPD is used (IPARAM(7) = 4). | c | All these options may be changed by the user. For | c | details, see the documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 4 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------------% c | Call LAPACK routine to factor the tridiagonal matrix | c | (K-SIGMA*KG). The matrix A is the 1-d discrete | c | Laplacian on the interval [0,1] with zero Dirichlet | c | boundary condition. The matrix M is the associated | c | mass matrix arising from using piecewise linear | c | finite elements on the interval [0, 1]. | c %------------------------------------------------------% c h = one / real(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two / h - sigma * r1 adl(j) = -one / h- sigma * r2 20 continue call scopy (n, adl, 1, adu, 1) call sgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV5.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c c %-------------------------------------------% c | Perform y <--- OP*x = inv[K-SIGMA*KG]*K*x | c | to force starting vector into the range | c | of OP. The user should provide his/her | c | matrix vector multiplication routine and | c | a linear system solver here. The matrix | c | vector multiplication routine (K*x) takes | c | workd(ipntr(1)) as the input vector. The | c | final result is returned to | c | workd(ipntr(2)). | c %-------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) c call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in SDRV5.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %------------------------------------------% c | Perform y <-- OP*x=inv(K-sigma*KG)*K*x. | c | K*x has been saved in workd(ipntr(3)). | c | The user only needs the linear system | c | solver here that takes workd(ipntr(3)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %------------------------------------------% c call scopy ( n, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV5.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %---------------------------------------------% c | Perform y <--- K*x | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %---------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) c c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SSAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c if (ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ',ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) c 30 continue c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV5 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is', n print *, ' The number of Ritz values requested is', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv5. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1-dimensional mass matrix c arising from using piecewise linear finite elements on the c interval [0,1]. c subroutine mv (n, v, w) integer n, j Real & v(n),w(n), one, four, six, h parameter (one = 1.0E+0, four = 4.0E+0, & six = 6.0E+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (six*real(n+1)) call sscal(n, h, w, 1) return end c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the stiffness matrix obtained from the c finite element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c subroutine av (n, v, w) integer n, j Real & v(n), w(n), one, two, h parameter (one = 1.0E+0, two = 2.0E+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h) c h = one / (n+1) call sscal(n, one/h, w, 1) return end arpack-ng-3.3.0/EXAMPLES/SYM/ssdrv6.f000066400000000000000000000427471260666001200166610ustar00rootroot00000000000000 program ssdrv6 c c Program to illustrate the idea of reverse communication c in Cayley mode for a generalized symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c sgttrf.f and sgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example six of ex-sym.doc in DOCUMENTS directory c c\Example-6 c ... Suppose we want to solve A*x = lambda*M*x in inverse mode, c where A and M are obtained by the finite element of the c 1-dimensional discrete Laplacian c d^2u / dx^2 c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c c ... OP = (inv[A-sigma*M])*(A+sigma*M) and B = M. c c ... Use mode 5 of SSAUPD. c c\BeginLib c c\References: c 1. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c c\Routines called: c ssaupd ARPACK reverse communication interface routine. c sseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c sgttrf LAPACK tridiagonal factorization routine. c sgttrs LAPACK tridiagonal solve routine. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector by a scalar. c snrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Danny Sorensen c Richard Lehoucq c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv6.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c------------------------------------------------------------------------ c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & temp(maxn), ax(maxn), mx(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Real & sigma, r1, r2, tol, h c c %------------% c | Parameters | c %------------% c Real & zero, one, two, four, six parameter (zero = 0.0E+0, one = 1.0E+0, & four = 4.0E+0, six = 6.0E+0, & two = 2.0E+0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & snrm2 external saxpy, scopy, sscal, snrm2, sgttrf, sgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable statements | c %-----------------------% c c %--------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'.) NEV is the number of eigenvalues to be | c | approximated. Since the Cayley mode is used, | c | WHICH is set to 'LM'. The user can modify NEV, | c | NCV, SIGMA to solve problems of different sizes, | c | and to get different parts of the spectrum. | c | However, The following conditions must be | c | satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %--------------------------------------------------% c n = 100 nev = 4 ncv = 20 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV6: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV6: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV6: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' sigma = 1.5E+2 c c %--------------------------------------------------% c | The work array WORKL is used in SSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 5 specified in the | c | documentation of SSAUPD is used (IPARAM(7) = 5). | c | All these options may be changed by the user. For | c | details, see the documentation in SSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 5 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %------------------------------------------------------% c | Call LAPACK routine to factor (A-sigma*M). The | c | stiffness matrix A is the 1-d discrete Laplacian. | c | The mass matrix M is the associated mass matrix | c | arising from using piecewise linear finite elements | c | on the interval [0, 1]. | c %------------------------------------------------------% c h = one / real(n+1) r1 = (four / six) * h r2 = (one / six) * h do 20 j=1,n ad(j) = two / h - sigma * r1 adl(j) = -one / h - sigma * r2 20 continue call scopy (n, adl, 1, adu, 1) call sgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in _SDRV6.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call ssaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1) then c c %-------------------------------------------------------% c | Perform y <--- OP*x = (inv[A-SIGMA*M])*(A+SIGMA*M)*x | c | to force starting vector into the range of OP. The | c | user should provide his/her matrix vector (A*x, M*x) | c | multiplication routines and a linear system solver | c | here. The matrix vector multiplication routine takes | c | workd(ipntr(1)) as the input vector. The final | c | result is returned to workd(ipntr(2)). | c %-------------------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call mv (n, workd(ipntr(1)), temp) call saxpy(n, sigma, temp, 1, workd(ipntr(2)), 1) c call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV6.' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 1) then c c %----------------------------------------------------% c | Perform y <-- OP*x = inv[A-SIGMA*M]*(A+SIGMA*M)*x. | c | M*x has been saved in workd(ipntr(3)). The user | c | need the matrix vector multiplication (A*x) | c | routine and a linear system solver here. The | c | matrix vector multiplication routine takes | c | workd(ipntr(1)) as the input, and the result is | c | combined with workd(ipntr(3)) to form the input | c | for the linear system solver. The final result is | c | returned to workd(ipntr(2)). | c %----------------------------------------------------% c call av (n, workd(ipntr(1)), workd(ipntr(2))) call saxpy(n, sigma, workd(ipntr(3)), 1, workd(ipntr(2)), 1) call sgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV6. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c else if (ido .eq. 2) then c c %--------------------------------------------% c | Perform y <--- M*x. | c | Need matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as input | c | and returns the result to workd(ipntr(2)). | c %--------------------------------------------% c call mv (n, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in SSAUPD | c %--------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check the documentation of _saupd. ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call sseupd ( rvec, 'All', select, d, v, ldv, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c nconv = iparam(5) do 30 j=1, nconv call av(n, v(1,j), ax) call mv(n, v(1,j), mx) call saxpy (n, -d(j,1), mx, 1, ax, 1) d(j,2) = snrm2(n, ax, 1) d(j,2) = d(j,2) / abs(d(j,1)) 30 continue c call smout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV6 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is', n print *, ' The number of Ritz values requested is', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program ssdrv6. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix used is the 1 dimensional mass matrix c arising from using the piecewise linear finite element c on the interval [0,1]. c subroutine mv (n, v, w) integer n, j Real & v(n), w(n), one, four, six, h parameter (one = 1.0E+0, four = 4.0E+0, & six = 6.0E+0) c w(1) = four*v(1) + v(2) do 100 j = 2,n-1 w(j) = v(j-1) + four*v(j) + v(j+1) 100 continue j = n w(j) = v(j-1) + four*v(j) c c Scale the vector w by h. c h = one / (six*real(n+1)) call sscal(n, h, w, 1) return end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the stiffness matrix obtained from the c finite element discretization of the 1-dimensional discrete Laplacian c on the interval [0,1] with zero Dirichlet boundary condition c using piecewise linear elements. c subroutine av (n, v, w) integer n, j Real & v(n), w(n), one, two, h parameter (one = 1.0E+0, two = 2.0E+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1/h). c h = one / real(n+1) call sscal(n, one/h, w, 1) return end arpack-ng-3.3.0/Makefile.am000066400000000000000000000014011260666001200154070ustar00rootroot00000000000000SUBDIRS = UTIL SRC . TESTS EXAMPLES if MPI SUBDIRS += PARPACK AM_DISTCHECK_CONFIGURE_FLAGS = --enable-mpi endif lib_LTLIBRARIES = libarpack.la ACLOCAL_AMFLAGS = -I m4 libarpack_la_SOURCES = # Force libarpack to be linked with the Fortran compiler. # The file dummy.f does not need to exist in the source tree. nodist_EXTRA_libarpack_la_SOURCES = dummy.f libarpack_la_LDFLAGS = -no-undefined -version-info 2:0 libarpack_la_LIBADD = \ $(top_builddir)/SRC/libarpacksrc.la \ $(top_builddir)/UTIL/libarpackutil.la \ $(LAPACK_LIBS) $(BLAS_LIBS) EXTRA_DIST = README PARPACK_CHANGES CHANGES DOCUMENTS VISUAL_STUDIO \ detect_arpack_bug.m4 # Pkgconfig directory pkgconfigdir = $(libdir)/pkgconfig # Files to install in Pkgconfig directory pkgconfig_DATA = arpack.pc arpack-ng-3.3.0/PARPACK/000077500000000000000000000000001260666001200144405ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/EXAMPLES/000077500000000000000000000000001260666001200156565ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/000077500000000000000000000000001260666001200165025ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/Makefile.am000066400000000000000000000022111260666001200205320ustar00rootroot00000000000000#LDADD = $(top_builddir)/PARPACK/SRC/BLACS/libparpacksrc.la $(BLAS_LIBS) $(LAPACK_LIBS) #SNDRV = psndrv1 psndrv3 #DNDRV = pdndrv1 pdndrv3 #SSDRV = pssdrv1 #DSDRV = pdsdrv1 #CNDRV = pcndrv1 #ZNDRV = pzndrv1 #NTEST = psntest1 pdntest1 #check_PROGRAMS = $(SNDRV) $(DNDRV) $(SSDRV) $(DSDRV) $(CNDRV) $(ZNDRV) $(NTEST) #TESTS = $(check_PROGRAMS) EXTRA_DIST = debug.h stat.h \ psndrv1.f psndrv3.f \ pdndrv1.f pdndrv3.f \ pssdrv1.f pdsdrv1.f \ pcndrv1.f pzndrv1.f \ psntest1.f pdntest1.f # Simple nonsymmetric problem using single precision #psndrv1_SOURCES = psndrv1.f #psndrv3_SOURCES = psndrv3.f # Simple nonsymmetric problem using double precision #pdndrv1_SOURCES = pdndrv1.f #pdndrv3_SOURCES = pdndrv3.f # Simple symmetric problem using single precision #pssdrv1_SOURCES = pssdrv1.f # Simple symmetric problem using double precision #pdsdrv1_SOURCES = pdsdrv1.f # Complex problem using single complex #pcndrv1_SOURCES = pcndrv1.f # Complex problem using double complex #pzndrv1_SOURCES = pzndrv1.f # Test routines for timing #psntest1_SOURCES = psntest1.f #pdntest1_SOURCES = pdntest1.f arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/debug.h000066400000000000000000000013511260666001200177410ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pcndrv1.f000066400000000000000000000430441260666001200202330ustar00rootroot00000000000000 program pcndrv1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c in the domain omega = (0,1)x(0,1), with c u = 0 on the boundary of omega. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x c ... Use mode 1 of PCNAUPD. c c\BeginLib c c\Routines called c pcnaupd Parallel ARPACK reverse communication interface routine. c pcneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a complex vector. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: ndrv1.F SID: 2.1 c c\SCCS Information: c FILE: ndrv1.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Real & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex & sigma Real & tol logical rvec c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Complex & mv_buf(maxn) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & pscnorm2 external pscnorm2, caxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mcaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of CNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pcnaupd ( comm, ido, bmat, nloc, which, & nev, tol, resid, ncv, v, ldv, iparam, ipntr, & workd, workl, lworkl, rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in CNAUPD | c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pcneupd (comm, rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, nloc, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call caxpy(nloc, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real(d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = pscnorm2(comm, nloc, ax, 1) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program pcndrv1. | c %----------------------------% c 9000 continue c c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w ) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, cgesd2d, cgerv2d c integer nloc, nx, np, j, lo, next, prev Complex & v(nloc), w(nloc), mv_buf(nx), one parameter (one = (1.0, 0.0)) external caxpy, tv c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call caxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call caxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call cgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call cgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call caxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call cgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call cgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call caxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex & x(nx), y(nx), h, dd, dl, du c Complex & one, rho parameter (one = (1.0, 0.0), rho = (100.0, 0.0)) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / cmplx(nx+1) dd = (4.0, 0.0) dl = -one - (0.5, 0.0)*rho*h du = -one + (0.5, 0.0)*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pdndrv1.f000066400000000000000000000466571260666001200202510ustar00rootroot00000000000000 program pdndrv1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x. c ... Use mode 1 of PDNAUPD. c c\BeginLib c c\Routines called: c pdnaupd Parallel ARPACK reverse communication interface routine. c pdneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv1.F SID: 2.2 c c\SCCS Information: c FILE: ndrv1.F SID: 1.2 DATE OF SID: 8/14/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=12, maxncv=30, ldv=maxnloc) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxnloc), d(maxncv,3), resid(maxnloc), & v(ldv,maxncv), workd(3*maxnloc), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Double precision & tol, sigmar, sigmai logical first, rvec c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Double precision & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, pdnorm2 external dlapy2, daxpy, pdnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in PDNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PDNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PDNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PDNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PDNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PDNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PDNAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PDNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pdneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PDNEUPD.| c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call daxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) call av(comm, nloc, nx, mv_buf, v(1,j+1), ax) call daxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call daxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2(d(j,3), pdnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, dgesd2d, dgerv2d c integer nloc, nx, np, j, lo, next, prev Double precision & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external daxpy, tv c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call dgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call dgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call daxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call dgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call dgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call daxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), h, dd, dl, du c Double precision & one, zero, rho parameter (one = 1.0, zero = 0.0, & rho = 0.0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / dble(nx+1) dd = 4.0*one dl = -one - 0.5*rho*h du = -one + 0.5*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pdndrv3.f000066400000000000000000000520511260666001200202340ustar00rootroot00000000000000 program psndrv3 c c Message Passing Layer: BLACS c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A is derived from the 1-dimensional convection-diffusion c operator on the interval [0,1] with zero boundary condition, c and M is the tridiagonal matrix with 4 on the diagonal and 1 c on the subdiagonals. c ... So OP = inv[M]*A and B = M. c ... Use mode 2 of PDNAUPD. c c\BeginLib c c\Routines called: c pdnaupd Parallel ARPACK reverse communication interface routine. c pdneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dpttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c dpttrs LAPACK symmetric positive definite tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Parallel Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv3.F SID: 2.2 c c\SCCS Information: c FILE: ndrv3.F SID: 1.2 DATE OF SID: 09/14/98 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1), temp(maxn), temp_buf(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode, blk Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero, one parameter (zero = 0.0, one = 1.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Double precision & pdnorm2, dlapy2 external daxpy, pdnorm2, dpttrf, dpttrs, dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (n / nprocs ) blk = nloc if ( mod(n, nprocs) .gt. 0 ) then if ( myprow .eq. nprow-1 ) nloc = nloc + mod(n, nprocs) * if ( mod(n, nprocs) .gt. myprow ) nloc = nloc + 1 endif c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV3: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | dpttrf. | c %-----------------------------------------------------% c do 20 j = 1, n-1 md(j) = 4.0 me(j) = one 20 continue md(n) = 4.0*one c call dpttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdnaupd( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (comm, nloc, n, workd(ipntr(1)), workd(ipntr(2))) c======== Hack for Linear system ======= ccc call dscal(n, zero, temp, 1) do 15 j=1,nloc temp(myprow*blk + j) = workd(ipntr(2) + j - 1) 15 continue call dgsum2d( comm, 'All', ' ', n, 1, temp, n, -1, -1 ) call dpttrs(n, 1, md, me, temp, n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if do 16 j=1,nloc workd(ipntr(2) + j - 1 ) = temp(myprow*blk + j) 16 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (comm, nloc, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %---------------------------% c | Error message. Check the | c | documentation in PDNAUPD. | c %---------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call pdneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) d(j,3) = pdnorm2(comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j+1), mx) call daxpy(nloc, d(j,2), mx, 1, ax, 1) d(j,3) = pdnorm2(comm, nloc, ax, 1)**2 call av(comm, nloc, n, v(1,j+1), ax) call mv(comm, nloc, v(1,j+1), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), pdnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program psndrv3. | c %----------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector multiplication subroutine c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived c from the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c subroutine av (comm, nloc, n, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, dgesd2d, dgerv2d c integer nloc, n, j, next, prev Double precision & v(nloc), w(nloc), one, two, dd, dl, du, & s, h, rho, mv_buf parameter ( rho = 10.0, one = 1.0, & two = 2.0) c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) h = one / dble(n+1) s = rho*h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,nloc-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(nloc) = dl*v(nloc-1) + dd*v(nloc) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call dgesd2d( comm, 1, 1, v(nloc), 1, next, mypcol) endif if ( myprow .gt. 0 ) then call dgerv2d( comm, 1, 1, mv_buf, 1, prev, mypcol ) w(1) = w(1) + dl*mv_buf endif c if ( myprow .gt. 0 ) then call dgesd2d( comm, 1, 1, v(1), 1, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call dgerv2d( comm, 1, 1, mv_buf, 1, next, mypcol ) w(nloc) = w(nloc) + du*mv_buf endif c return end c------------------------------------------------------------------------ c c Compute the matrix vector multiplication y<---M*x c where M is a n by n tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and the superdiagonal. c subroutine mv (comm, nloc, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, dgesd2d, dgerv2d c integer nloc, j, next, prev Double precision & v(nloc), w(nloc), one, four, mv_buf parameter ( one = 1.0, four = 4.0) c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c w(1) = four*v(1) + one*v(2) do 10 j = 2,nloc-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(nloc) = one*v(nloc-1) + four*v(nloc) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call dgesd2d( comm, 1, 1, v(nloc), 1, next, mypcol) endif if ( myprow .gt. 0 ) then call dgerv2d( comm, 1, 1, mv_buf, 1, prev, mypcol ) w(1) = w(1) + mv_buf endif c if ( myprow .gt. 0 ) then call dgesd2d( comm, 1, 1, v(1), 1, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call dgerv2d( comm, 1, 1, mv_buf, 1, next, mypcol ) w(nloc) = w(nloc) + mv_buf endif c return end c------------------------------------------------------------ subroutine mv2 (comm, n, v, w) integer n, j, comm Double precision & v(n), w(n) do 10 j=1,n w(j) = v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pdntest1.f000066400000000000000000000357051260666001200204250ustar00rootroot00000000000000 program psntest1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Test-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is random diagonal matrix with 4 separated eigenvalues. c ... OP = A and B = I. c ... Assume "call av ( nloc, diag, x, y)" computes y = A*x. c ... Use mode 1 of PDNAUPD. c c\BeginLib c c\Routines called: c pdnaupd Parallel ARPACK reverse communication interface routine. c pdneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c c\Author c Kristi Maschhoff c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: c FILE: %M% SID: %I% DATE OF SID: %G% RELEASE: %R% c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=100000, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), iseed(4) logical select(maxncv) Double precision & ax(maxn), d(maxncv,3), resid(maxn), diag(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode, idist Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero, one parameter ( zero = 0.0, one = 1.0 ) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, pdnorm2 external dlapy2, daxpy, pdnorm2, dlarnv c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c n = maxn*nprocs nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = maxn c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %-----------------------------------% c | Generate random diagonal matrix | c | Isolate 4 extreamal eigenvalues | c %-----------------------------------% c idist = 1 iseed(1) = 15 iseed(2) = 35 iseed(3) = 52 iseed(4) = 7 call dlarnv ( idist, iseed, nloc, diag ) diag(1) = diag(1) + 1.01 diag(2) = diag(2) + 1.01 diag(3) = diag(3) + 1.01 diag(4) = diag(4) + 1.01 c c %-----------------------------------------------------% c | The work array WORKL is used in PDNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PDNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 1 do 50 j=1,nloc resid(j) = 1.0 50 continue c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PDNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PDNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PDNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( nloc, diag, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PDNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PDNAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PDNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pdneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PDNEUPD.| c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av( nloc, diag, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av( nloc, diag, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call daxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) call av( nloc, diag, v(1,j+1), ax) call daxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call daxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2(d(j,3), pdnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c subroutine av (n, diag, v, w) integer n, j Double precision & v(n), w(n), diag(n) c do 10 j = 1, n w(j) = diag(j)*v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pdsdrv1.f000066400000000000000000000423061260666001200202410ustar00rootroot00000000000000 program pdsdrv1 c c Message Passing Layer: BLACS c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x. c ... Use mode 1 of DSAUPD. c c\BeginLib c c\Routines called: c pdsaupd Parallel ARPACK reverse communication interface routine. c pdseupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sdrv1.F SID: 2.2 c c FILE: sdrv1.F SID: 1.4 DATE OF SID: 3/19/97 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=10, maxncv=25, & ldv=maxnloc ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxnloc), d(maxncv,2), resid(maxnloc), & ax(maxnloc) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Double precision & tol, sigma c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Double precision & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & pdnorm2 external pdnorm2, daxpy c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 msaupd = 1 c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _SDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in PSSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in PSSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSSAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdsaupd ( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSSAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in PSSAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pdseupd ( comm, rvec, 'All', select, & d, v, ldv, sigma, & bmat, nloc, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSSEUPD.| c %------------------------------------% c c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = pdnorm2( comm, nloc, ax, 1 ) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call pdmout(comm, 6, nconv, 2, d, maxncv, -6, & 'Ritz values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_SDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' endif c end if c c %---------------------------% c | Done with program pdsdrv1.| c %---------------------------% c 9000 continue c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c ------------------------------------------------------------------ c parallel matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c------------------------------------------------------------------- c subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, DGESD2D, DGERV2D integer nloc, nx, np, j, lo, next, prev Double precision & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external daxpy call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c if ( np .gt. 2) then do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue end if c if ( np .gt. 1) then lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) end if c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call dgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call dgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call daxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call dgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call dgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call daxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), dd, dl, du c Double precision & one parameter (one = 1.0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/psndrv1.f000066400000000000000000000465171260666001200202630ustar00rootroot00000000000000 program psndrv1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x. c ... Use mode 1 of PSNAUPD. c c\BeginLib c c\Routines called: c psnaupd Parallel ARPACK reverse communication interface routine. c psneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv1.F SID: 2.2 c c\SCCS Information: c FILE: ndrv1.F SID: 1.2 DATE OF SID: 8/14/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=12, maxncv=30, ldv=maxnloc) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxnloc), d(maxncv,3), resid(maxnloc), & v(ldv,maxncv), workd(3*maxnloc), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Real & tol, sigmar, sigmai logical first, rvec c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Real & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, psnorm2 external slapy2, saxpy, psnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in PSNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PSNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call psnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PSNAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call psneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSNEUPD.| c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call saxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) call av(comm, nloc, nx, mv_buf, v(1,j+1), ax) call saxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call saxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2(d(j,3), psnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, sgesd2d, sgerv2d c integer nloc, nx, np, j, lo, next, prev Real & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external saxpy, tv c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call sgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call sgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call saxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call sgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call sgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call saxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), h, dd, dl, du c Real & one, zero, rho parameter (one = 1.0, zero = 0.0, & rho = 0.0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / dble(nx+1) dd = 4.0*one dl = -one - 0.5*rho*h du = -one + 0.5*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/psndrv3.f000066400000000000000000000517251260666001200202620ustar00rootroot00000000000000 program psndrv3 c c Message Passing Layer: BLACS c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A is derived from the 1-dimensional convection-diffusion c operator on the interval [0,1] with zero boundary condition, c and M is the tridiagonal matrix with 4 on the diagonal and 1 c on the subdiagonals. c ... So OP = inv[M]*A and B = M. c ... Use mode 2 of PSNAUPD. c c\BeginLib c c\Routines called: c psnaupd Parallel ARPACK reverse communication interface routine. c psneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c spttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c spttrs LAPACK symmetric positive definite tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Parallel Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv3.F SID: 2.2 c c\SCCS Information: c FILE: ndrv3.F SID: 1.2 DATE OF SID: 09/14/98 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1), temp(maxn), temp_buf(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode, blk Real & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero, one parameter (zero = 0.0, one = 1.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Real & psnorm2, slapy2 external saxpy, psnorm2, spttrf, spttrs, slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (n / nprocs ) blk = nloc if ( mod(n, nprocs) .gt. 0 ) then if ( myprow .eq. nprow-1 ) nloc = nloc + mod(n, nprocs) * if ( mod(n, nprocs) .gt. myprow ) nloc = nloc + 1 endif c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV3: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | spttrf. | c %-----------------------------------------------------% c do 20 j = 1, n-1 md(j) = 4.0 me(j) = one 20 continue md(n) = 4.0*one c call spttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call psnaupd( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (comm, nloc, n, workd(ipntr(1)), workd(ipntr(2))) c======== Hack for Linear system ======= ccc call sscal(n, zero, temp, 1) do 15 j=1,nloc temp(myprow*blk + j) = workd(ipntr(2) + j - 1) 15 continue call sgsum2d( comm, 'All', ' ', n, 1, temp, n, -1, -1 ) call spttrs(n, 1, md, me, temp, n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if do 16 j=1,nloc workd(ipntr(2) + j - 1 ) = temp(myprow*blk + j) 16 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (comm, nloc, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %---------------------------% c | Error message. Check the | c | documentation in PSNAUPD. | c %---------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call psneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) d(j,3) = psnorm2(comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j+1), mx) call saxpy(nloc, d(j,2), mx, 1, ax, 1) d(j,3) = psnorm2(comm, nloc, ax, 1)**2 call av(comm, nloc, n, v(1,j+1), ax) call mv(comm, nloc, v(1,j+1), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), psnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program psndrv3. | c %----------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector multiplication subroutine c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived c from the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c subroutine av (comm, nloc, n, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, sgesd2d, sgerv2d c integer nloc, n, j, next, prev Real & v(nloc), w(nloc), one, two, dd, dl, du, & s, h, rho, mv_buf parameter ( rho = 10.0, one = 1.0, & two = 2.0) c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) h = one / real(n+1) s = rho*h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,nloc-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(nloc) = dl*v(nloc-1) + dd*v(nloc) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call sgesd2d( comm, 1, 1, v(nloc), 1, next, mypcol) endif if ( myprow .gt. 0 ) then call sgerv2d( comm, 1, 1, mv_buf, 1, prev, mypcol ) w(1) = w(1) + dl*mv_buf endif c if ( myprow .gt. 0 ) then call sgesd2d( comm, 1, 1, v(1), 1, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call sgerv2d( comm, 1, 1, mv_buf, 1, next, mypcol ) w(nloc) = w(nloc) + du*mv_buf endif c return end c------------------------------------------------------------------------ c c Compute the matrix vector multiplication y<---M*x c where M is a n by n tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and the superdiagonal. c subroutine mv (comm, nloc, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, sgesd2d, sgerv2d c integer nloc, j, next, prev Real & v(nloc), w(nloc), one, four, mv_buf parameter ( one = 1.0, four = 4.0) c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c w(1) = four*v(1) + one*v(2) do 10 j = 2,nloc-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(nloc) = one*v(nloc-1) + four*v(nloc) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call sgesd2d( comm, 1, 1, v(nloc), 1, next, mypcol) endif if ( myprow .gt. 0 ) then call sgerv2d( comm, 1, 1, mv_buf, 1, prev, mypcol ) w(1) = w(1) + mv_buf endif c if ( myprow .gt. 0 ) then call sgesd2d( comm, 1, 1, v(1), 1, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call sgerv2d( comm, 1, 1, mv_buf, 1, next, mypcol ) w(nloc) = w(nloc) + mv_buf endif c return end c------------------------------------------------------------ subroutine mv2 (comm, n, v, w) integer n, j, comm Real & v(n), w(n) do 10 j=1,n w(j) = v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/psntest1.f000066400000000000000000000356061260666001200204440ustar00rootroot00000000000000 program psntest1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Test-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is random diagonal matrix with 4 separated eigenvalues. c ... OP = A and B = I. c ... Assume "call av ( nloc, diag, x, y)" computes y = A*x. c ... Use mode 1 of PSNAUPD. c c\BeginLib c c\Routines called: c psnaupd Parallel ARPACK reverse communication interface routine. c psneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c c\Author c Kristi Maschhoff c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: c FILE: %M% SID: %I% DATE OF SID: %G% RELEASE: %R% c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14), iseed(4) logical select(maxncv) Real & ax(maxn), d(maxncv,3), resid(maxn), diag(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode, idist Real & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero, one parameter (zero = 0.0, one = 1.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, psnorm2 external slapy2, saxpy, psnorm2, slarnv c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mnaupd = 1 c n = 10000*nprocs nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = 10000 c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------% c | Generate random diagonal matrix | c | Isolate 4 extreamal eigenvalues | c %-----------------------------------% c idist = 1 iseed(1) = 15 iseed(2) = 35 iseed(3) = 52 iseed(4) = 7 call slarnv ( idist, iseed, nloc, diag ) diag(1) = diag(1) + 1.01 diag(2) = diag(2) + 1.01 diag(3) = diag(3) + 1.01 diag(4) = diag(4) + 1.01 c c %-----------------------------------------------------% c | The work array WORKL is used in PSNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 1 do 50 j=1,nloc resid(j) = one 50 continue c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PSNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call psnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( nloc, diag, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PSNAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call psneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSNEUPD.| c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av( nloc, diag, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av( nloc, diag, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call saxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) call av( nloc, diag, v(1,j+1), ax) call saxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call saxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2(d(j,3), psnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c subroutine av (n, diag, v, w) integer n, j Real & v(n), w(n), diag(n) c do 10 j = 1, n w(j) = diag(j)*v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pssdrv1.f000066400000000000000000000421461260666001200202620ustar00rootroot00000000000000 program pssdrv1 c c Message Passing Layer: BLACS c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x. c ... Use mode 1 of SSAUPD. c c\BeginLib c c\Routines called: c pssaupd Parallel ARPACK reverse communication interface routine. c psseupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sdrv1.F SID: 2.2 c c FILE: sdrv1.F SID: 1.4 DATE OF SID: 3/19/97 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=10, maxncv=25, & ldv=maxnloc ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxnloc), d(maxncv,2), resid(maxnloc), & ax(maxnloc) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Real & tol, sigma c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Real & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & psnorm2 external psnorm2, saxpy c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 msaupd = 1 c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _SDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in PSSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in PSSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSSAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pssaupd ( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSSAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in PSSAUPD.| c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call psseupd ( comm, rvec, 'All', select, & d, v, ldv, sigma, & bmat, nloc, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSSEUPD.| c %------------------------------------% c c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = psnorm2( comm, nloc, ax, 1 ) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call psmout(comm, 6, nconv, 2, d, maxncv, -6, & 'Ritz values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_SDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' endif c end if c c %---------------------------% c | Done with program pssdrv1.| c %---------------------------% c 9000 continue c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c ------------------------------------------------------------------ c parallel matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c------------------------------------------------------------------- c subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, SGESD2D, SGERV2D integer nloc, nx, np, j, lo, next, prev Real & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external saxpy call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c if ( np .gt. 2) then do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue end if c if ( np .gt. 1) then lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) end if c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call sgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call sgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call saxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call sgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call sgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call saxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), dd, dl, du c Real & one parameter (one = 1.0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/pzndrv1.f000066400000000000000000000431331260666001200202610ustar00rootroot00000000000000 program pzndrv1 c c Message Passing Layer: BLACS c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c in the domain omega = (0,1)x(0,1), with c u = 0 on the boundary of omega. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x c ... Use mode 1 of PZNAUPD. c c\BeginLib c c\Routines called c pznaupd Parallel ARPACK reverse communication interface routine. c pzneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a complex vector. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: ndrv1.F SID: 2.1 c c\SCCS Information: c FILE: ndrv1.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'debug.h' include 'stat.h' c c %-----------------% c | BLACS INTERFACE | c %-----------------% c integer comm, iam, nprocs, nloc, & nprow, npcol, myprow, mypcol c external BLACS_PINFO, BLACS_SETUP, BLACS_GET, & BLACS_GRIDINIT, BLACS_GRIDINFO c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex*16 & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Double precision & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex*16 & sigma Double precision & tol logical rvec c c %----------------------------------------------% c | Local Buffers needed for BLACS communication | c %----------------------------------------------% c Complex*16 & mv_buf(maxn) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & pdznorm2 external pdznorm2, zaxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c call BLACS_PINFO( iam, nprocs ) c c If in PVM, create virtual machine if it doesn't exist c if (nprocs .lt. 1) then if (iam .eq. 0) then write(*,1000) read(*, 2000) nprocs endif call BLACS_SETUP( iam, nprocs ) endif c 1000 format('How many processes in machine?') 2000 format(I3) c c Set up processors in 1D Grid c nprow = nprocs npcol = 1 c c Get default system context, and define grid c call BLACS_GET( 0, 0, comm ) call BLACS_GRIDINIT( comm, 'Row', nprow, npcol ) call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c c If I'm not in grid, go to end of program c if ( (myprow .ge. nprow) .or. (mypcol .ge. npcol) ) goto 9000 c ndigit = -3 logfil = 6 mcaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myprow ) nloc = nloc + nx c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of ZNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | ZNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pznaupd ( comm, ido, bmat, nloc, which, & nev, tol, resid, ncv, v, ldv, iparam, ipntr, & workd, workl, lworkl, rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %--------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pzneupd (comm, rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, nloc, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD. | c %------------------------------------% c if ( myprow .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call zaxpy(nloc, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble(d(j)) rd(j,2) = dimag(d(j)) rd(j,3) = pdznorm2(comm, nloc, ax, 1) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myprow .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program pzndrv1. | c %----------------------------% c 9000 continue c c c %-------------------------% c | Release resources BLACS | c %-------------------------% c call BLACS_GRIDEXIT ( comm ) call BLACS_EXIT(0) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w ) c c .. BLACS Declarations ... integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO, zgesd2d, zgerv2d c integer nloc, nx, np, j, lo, next, prev Complex*16 & v(nloc), w(nloc), mv_buf(nx), one parameter (one = (1.0, 0.0)) external zaxpy, tv c call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) c np = nloc/nx call tv(nx,v(1),w(1)) call zaxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call zaxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myprow + 1 prev = myprow - 1 if ( myprow .lt. nprow-1 ) then call zgesd2d( comm, nx, 1, v((np-1)*nx+1), nx, next, mypcol) endif if ( myprow .gt. 0 ) then call zgerv2d( comm, nx, 1, mv_buf, nx, prev, mypcol ) call zaxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myprow .gt. 0 ) then call zgesd2d( comm, nx, 1, v(1), nx, prev, mypcol) endif if ( myprow .lt. nprow-1 ) then call zgerv2d( comm, nx, 1, mv_buf, nx, next, mypcol ) call zaxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex*16 & x(nx), y(nx), h, dd, dl, du c Complex*16 & one, rho parameter (one = (1.0, 0.0), rho = (100.0, 0.0)) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / dcmplx(nx+1) dd = (4.0, 0.0) dl = -one - (0.5, 0.0)*rho*h du = -one + (0.5, 0.0)*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/BLACS/stat.h000066400000000000000000000017131260666001200176300ustar00rootroot00000000000000c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c c\SCCS Information: @(#) c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2 c real t0, t1, t2, t3, t4, t5 save t0, t1, t2, t3, t4, t5 c integer nopx, nbx, nrorth, nitref, nrstrt real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec common /timing/ & nopx, nbx, nrorth, nitref, nrstrt, & tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/000077500000000000000000000000001260666001200163035ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/Makefile.am000066400000000000000000000016031260666001200203370ustar00rootroot00000000000000F77 = $(MPIF77) LDADD = $(top_builddir)/PARPACK/libparpack.la $(BLAS_LIBS) $(LAPACK_LIBS) SNDRV = psndrv1 psndrv3 DNDRV = pdndrv1 pdndrv3 SSDRV = pssdrv1 DSDRV = pdsdrv1 CNDRV = pcndrv1 ZNDRV = pzndrv1 check_PROGRAMS = $(SNDRV) $(DNDRV) $(SSDRV) $(DSDRV) $(CNDRV) $(ZNDRV) # Disable tests for now. Needs to be run using mpirun #TESTS = $(check_PROGRAMS) EXTRA_DIST = debug.h stat.h # Simple nonsymmetric problem using single precision psndrv1_SOURCES = psndrv1.f psndrv3_SOURCES = psndrv3.f # Simple nonsymmetric problem using double precision pdndrv1_SOURCES = pdndrv1.f pdndrv3_SOURCES = pdndrv3.f # Simple symmetric problem using single precision pssdrv1_SOURCES = pssdrv1.f # Simple symmetric problem using double precision pdsdrv1_SOURCES = pdsdrv1.f # Complex problem using single complex pcndrv1_SOURCES = pcndrv1.f # Complex problem using double complex pzndrv1_SOURCES = pzndrv1.f arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/debug.h000066400000000000000000000013511260666001200175420ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pcndrv1.f000066400000000000000000000416721260666001200200410ustar00rootroot00000000000000 program pcndrv1 c c Message Passing Layer: MPI c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c in the domain omega = (0,1)x(0,1), with c u = 0 on the boundary of omega. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x c ... Use mode 1 of PCNAUPD. c c\BeginLib c c\Routines called c pcnaupd Parallel ARPACK reverse communication interface routine. c pcneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a complex vector. c caxpy Level 1 BLAS that computes y <- alpha*x+y. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: ndrv1.F SID: 2.1 c c\SCCS Information: c FILE: ndrv1.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Real & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex & sigma Real & tol logical rvec c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Complex & mv_buf(maxn) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & pscnorm2 external pscnorm2, caxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mcaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in CNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of CNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | CNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine CNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pcnaupd ( comm, ido, bmat, nloc, which, & nev, tol, resid, ncv, v, ldv, iparam, ipntr, & workd, workl, lworkl, rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call CNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in CNAUPD | c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using CNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pcneupd (comm, rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, nloc, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of CNEUPD. | c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call caxpy(nloc, -d(j), v(1,j), 1, ax, 1) rd(j,1) = real(d(j)) rd(j,2) = aimag(d(j)) rd(j,3) = pscnorm2(comm, nloc, ax, 1) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program pcndrv1. | c %----------------------------% c 9000 continue c c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w ) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, nx, np, j, lo, next, prev Complex & v(nloc), w(nloc), mv_buf(nx), one parameter (one = (1.0, 0.0)) external caxpy, tv c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call caxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call caxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call caxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_COMPLEX, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_COMPLEX, prev, myid, & comm, status, ierr ) call caxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_COMPLEX, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_COMPLEX, next, myid, & comm, status, ierr ) call caxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex & x(nx), y(nx), h, dd, dl, du c Complex & one, rho parameter (one = (1.0, 0.0), rho = (100.0, 0.0)) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / cmplx(nx+1) dd = (4.0, 0.0) dl = -one - (0.5, 0.0)*rho*h du = -one + (0.5, 0.0)*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pdndrv1.f000066400000000000000000000455551260666001200200460ustar00rootroot00000000000000 program pdndrv1 c c Message Passing Layer: MPI c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x. c ... Use mode 1 of PDNAUPD. c c\BeginLib c c\Routines called: c pdnaupd Parallel ARPACK reverse communication interface routine. c pdneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv1.F SID: 2.2 c c\SCCS Information: c FILE: ndrv1.F SID: 1.2 DATE OF SID: 8/14/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=12, maxncv=30, ldv=maxnloc) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxnloc), d(maxncv,3), resid(maxnloc), & v(ldv,maxncv), workd(3*maxnloc), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Double precision & tol, sigmar, sigmai logical first, rvec c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Double precision & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, pdnorm2 external dlapy2, daxpy, pdnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mnaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in PDNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PDNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PDNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PDNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PDNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PDNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PDNAUPD.| c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PDNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pdneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PDNEUPD.| c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call daxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = pdnorm2( comm, nloc, ax, 1) call av(comm, nloc, nx, mv_buf, v(1,j+1), ax) call daxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call daxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2(d(j,3), pdnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, nx, np, j, lo, next, prev Double precision & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external daxpy, tv c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_DOUBLE_PRECISION, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_PRECISION, prev, myid, & comm, status, ierr ) call daxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_DOUBLE_PRECISION, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_PRECISION, next, myid, & comm, status, ierr ) call daxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), h, dd, dl, du c Double precision & one, zero, rho parameter (one = 1.0, zero = 0.0, & rho = 0.0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / dble(nx+1) dd = 4.0*one dl = -one - 0.5*rho*h du = -one + 0.5*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pdndrv3.f000066400000000000000000000514531260666001200200420ustar00rootroot00000000000000 program psndrv3 c c Message Passing Layer: MPI c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A is derived from the 1-dimensional convection-diffusion c operator on the interval [0,1] with zero boundary condition, c and M is the tridiagonal matrix with 4 on the diagonal and 1 c on the subdiagonals. c ... So OP = inv[M]*A and B = M. c ... Use mode 2 of PDNAUPD. c c\BeginLib c c\Routines called: c pdnaupd Parallel ARPACK reverse communication interface routine. c pdneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dpttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c dpttrs LAPACK symmetric positive definite tridiagonal solve routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Parallel Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv3.F SID: 2.2 c c\SCCS Information: c FILE: ndrv3.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1), temp(maxn), temp_buf(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode, blk Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero, one parameter (zero = 0.0, one = 1.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Double precision & pdnorm2, dlapy2 external daxpy, pdnorm2, dpttrf, dpttrs, dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mnaupd = 1 c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (n / nprocs ) blk = nloc if ( mod(n, nprocs) .gt. 0 ) then if ( myid .eq. nprocs-1 ) nloc = nloc + mod(n, nprocs) * if ( mod(n, nprocs) .gt. myid ) nloc = nloc + 1 endif c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV3: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | dpttrf. | c %-----------------------------------------------------% c do 20 j = 1, n-1 md(j) = 4.0 me(j) = one 20 continue md(n) = 4.0*one c call dpttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of DNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdnaupd( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (comm, nloc, n, workd(ipntr(1)), workd(ipntr(2))) c======== Hack for Linear system ======= ccc call dscal(n, zero, temp, 1) call dscal(n, zero, temp_buf, 1) do 15 j=1,nloc temp_buf(myid*blk + j) = workd(ipntr(2) + j - 1) 15 continue call MPI_ALLREDUCE( temp_buf, temp, n, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) call dpttrs(n, 1, md, me, temp, n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if do 16 j=1,nloc workd(ipntr(2) + j - 1 ) = temp(myid*blk + j) 16 continue c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (comm, nloc, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %---------------------------% c | Error message. Check the | c | documentation in PDNAUPD. | c %---------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call pdneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) d(j,3) = pdnorm2(comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j+1), mx) call daxpy(nloc, d(j,2), mx, 1, ax, 1) d(j,3) = pdnorm2(comm, nloc, ax, 1)**2 call av(comm, nloc, n, v(1,j+1), ax) call mv(comm, nloc, v(1,j+1), mx) call daxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j), mx) call daxpy(nloc, -d(j,2), mx, 1, ax, 1) d(j,3) = dlapy2( d(j,3), pdnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program psndrv3. | c %----------------------------% c 9000 continue c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector multiplication subroutine c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived c from the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c subroutine av (comm, nloc, n, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, n, j, next, prev Double precision & v(nloc), w(nloc), one, two, dd, dl, du, & s, h, rho, mv_buf parameter ( rho = 10.0, one = 1.0, & two = 2.0) c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) h = one / dble(n+1) s = rho*h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,nloc-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(nloc) = dl*v(nloc-1) + dd*v(nloc) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v(nloc), 1, MPI_DOUBLE_PRECISION, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, 1, MPI_DOUBLE_PRECISION, prev, myid, & comm, status, ierr ) w(1) = w(1) + dl*mv_buf endif c if ( myid .gt. 0 ) then call mpi_send( v(1), 1, MPI_DOUBLE_PRECISION, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, 1, MPI_DOUBLE_PRECISION, next, myid, & comm, status, ierr ) w(nloc) = w(nloc) + du*mv_buf endif c return end c------------------------------------------------------------------------ c c Compute the matrix vector multiplication y<---M*x c where M is a n by n tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and the superdiagonal. c subroutine mv (comm, nloc, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, j, next, prev Double precision & v(nloc), w(nloc), one, four, mv_buf parameter ( one = 1.0, four = 4.0) c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c w(1) = four*v(1) + one*v(2) do 10 j = 2,nloc-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(nloc) = one*v(nloc-1) + four*v(nloc) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v(nloc), 1, MPI_DOUBLE_PRECISION, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, 1, MPI_DOUBLE_PRECISION, prev, myid, & comm, status, ierr ) w(1) = w(1) + mv_buf endif c if ( myid .gt. 0 ) then call mpi_send( v(1), 1, MPI_DOUBLE_PRECISION, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, 1, MPI_DOUBLE_PRECISION, next, myid, & comm, status, ierr ) w(nloc) = w(nloc) + mv_buf endif c return end c------------------------------------------------------------ subroutine mv2 (comm, n, v, w) integer n, j, comm Double precision & v(n), w(n) do 10 j=1,n w(j) = v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pdsdrv1.f000066400000000000000000000412031260666001200200350ustar00rootroot00000000000000 program pdsdrv1 c c Message Passing Layer: MPI c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x. c ... Use mode 1 of DSAUPD. c c\BeginLib c c\Routines called: c pdsaupd Parallel ARPACK reverse communication interface routine. c pdseupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sdrv1.F SID: 2.2 c c FILE: sdrv1.F SID: 1.4 DATE OF SID: 3/19/97 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=10, maxncv=25, & ldv=maxnloc ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxnloc), d(maxncv,2), resid(maxnloc), & ax(maxnloc) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Double precision & tol, sigma c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Double precision & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & pdnorm2 external pdnorm2, daxpy c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 msaupd = 1 c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _SDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in PSSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in PSSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSSAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pdsaupd ( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSSAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in PSSAUPD.| c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pdseupd ( comm, rvec, 'All', select, & d, v, ldv, sigma, & bmat, nloc, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSSEUPD.| c %------------------------------------% c c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call daxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = pdnorm2( comm, nloc, ax, 1 ) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call pdmout(comm, 6, nconv, 2, d, maxncv, -6, & 'Ritz values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_SDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' endif c end if c c %---------------------------% c | Done with program pdsdrv1.| c %---------------------------% c 9000 continue c call MPI_FINALIZE(rc) c end c c ------------------------------------------------------------------ c parallel matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c------------------------------------------------------------------- c subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) integer nloc, nx, np, j, lo, next, prev Double precision & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external daxpy call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call daxpy(nx, -one, v(nx+1), 1, w(1), 1) c if ( np .gt. 2) then do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call daxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue end if c if ( np .gt. 1) then lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call daxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) end if c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_DOUBLE_PRECISION, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_PRECISION, prev, myid, & comm, status, ierr ) call daxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_DOUBLE_PRECISION, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_PRECISION, next, myid, & comm, status, ierr ) call daxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Double precision & x(nx), y(nx), dd, dl, du c Double precision & one parameter (one = 1.0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/psndrv1.f000066400000000000000000000453351260666001200200610ustar00rootroot00000000000000 program psndrv1 c c Message Passing Layer: MPI c c Example program to illustrate the idea of reverse communication c for a standard nonsymmetric eigenvalue problem. c c We implement example one of ex-nonsym.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x. c ... Use mode 1 of PSNAUPD. c c\BeginLib c c\Routines called: c psnaupd Parallel ARPACK reverse communication interface routine. c psneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv1.F SID: 2.2 c c\SCCS Information: c FILE: ndrv1.F SID: 1.2 DATE OF SID: 8/14/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the distributed | c | block of A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=12, maxncv=30, ldv=maxnloc) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxnloc), d(maxncv,3), resid(maxnloc), & v(ldv,maxncv), workd(3*maxnloc), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Real & tol, sigmar, sigmai logical first, rvec c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Real & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & slapy2, psnorm2 external slapy2, saxpy, psnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mnaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %-----------------------------------------------------% c | The work array WORKL is used in PSNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSNAUPD to start the Arnoldi iteration.| c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | PSNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSNAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call psnaupd(comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSNAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in PSNAUPD.| c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call psneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the imaginary part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSNEUPD.| c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) call saxpy(nloc, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = psnorm2( comm, nloc, ax, 1) call av(comm, nloc, nx, mv_buf, v(1,j+1), ax) call saxpy(nloc, -d(j,2), v(1,j), 1, ax, 1) call saxpy(nloc, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = slapy2(d(j,3), psnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %---------------------------% c | Done with program pdndrv1.| c %---------------------------% c 9000 continue c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the 2 dimensional convection-diffusion c operator discretized using central difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the 2 dimensional convection-diffusion operator c (Laplacian u) + rho*(du/dx) on a unit square with zero boundary c condition. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c c The subroutine TV is called to compute y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, nx, np, j, lo, next, prev Real & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external saxpy, tv c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_REAL, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_REAL, prev, myid, & comm, status, ierr ) call saxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_REAL, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_REAL, next, myid, & comm, status, ierr ) call saxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), h, dd, dl, du c Real & one, zero, rho parameter (one = 1.0, zero = 0.0, & rho = 0.0) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c When rho*h/2 <= 1, the discrete convection-diffusion operator c has real eigenvalues. When rho*h/2 > 1, it has COMPLEX c eigenvalues. c h = one / dble(nx+1) dd = 4.0*one dl = -one - 0.5*rho*h du = -one + 0.5*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/psndrv3.f000066400000000000000000000511531260666001200200560ustar00rootroot00000000000000 program psndrv3 c c Message Passing Layer: MPI c c Simple program to illustrate the idea of reverse communication c in inverse mode for a generalized nonsymmetric eigenvalue problem. c c We implement example three of ex-nonsym.doc in DOCUMENTS directory c c\Example-3 c ... Suppose we want to solve A*x = lambda*B*x in inverse mode, c where A is derived from the 1-dimensional convection-diffusion c operator on the interval [0,1] with zero boundary condition, c and M is the tridiagonal matrix with 4 on the diagonal and 1 c on the subdiagonals. c ... So OP = inv[M]*A and B = M. c ... Use mode 2 of PSNAUPD. c c\BeginLib c c\Routines called: c psnaupd Parallel ARPACK reverse communication interface routine. c psneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c spttrf LAPACK symmetric positive definite tridiagonal factorization c routine. c spttrs LAPACK symmetric positive definite tridiagonal solve routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c av Parallel Matrix vector multiplication routine that computes A*x. c mv Matrix vector multiplication routine that computes M*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ndrv3.F SID: 2.2 c c\SCCS Information: c FILE: ndrv3.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c-------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Real & ax(maxn), mx(maxn), d(maxncv, 3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv), & md(maxn), me(maxn-1), temp(maxn), temp_buf(maxn) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nconv, maxitr, ishfts, mode, blk Real & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Real & zero, one parameter (zero = 0.0, one = 1.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% Real & psnorm2, slapy2 external saxpy, psnorm2, spttrf, spttrs, slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mnaupd = 1 c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | generalized eigenvalue problem is solved (BMAT = | c | 'G'). NEV is the number of eigenvalues to be | c | approximated. The user can modify NEV, NCV, WHICH | c | to solve problems of different sizes, and to get | c | different parts of the spectrum. However, The | c | following conditions must be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (n / nprocs ) blk = nloc if ( mod(n, nprocs) .gt. 0 ) then if ( myid .eq. nprocs-1 ) nloc = nloc + mod(n, nprocs) * if ( mod(n, nprocs) .gt. myid ) nloc = nloc + 1 endif c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV3: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV3: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV3: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'G' which = 'LM' c c %-----------------------------------------------------% c | The matrix M is chosen to be the symmetric tri- | c | diagonal matrix with 4 on the diagonal and 1 on the | c | off diagonals. It is factored by LAPACK subroutine | c | spttrf. | c %-----------------------------------------------------% c do 20 j = 1, n-1 md(j) = 4.0 me(j) = one 20 continue md(n) = 4.0*one c call spttrf(n, md, me, ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrf. ' print*, ' ' go to 9000 end if c c %-----------------------------------------------------% c | The work array WORKL is used in SNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in SNAUPD to start the Arnoldi iteration. | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 2 of SNAUPD is used | c | (IPARAM(7) = 2). All these options can be | c | changed by the user. For details, see the | c | documentation in SNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 2 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine SNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call psnaupd( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <--- OP*x = inv[M]*A*x | c | The user should supply his/her own | c | matrix vector routine and a linear | c | system solver. The matrix-vector | c | subroutine should take workd(ipntr(1)) | c | as input, and the final result should | c | be returned to workd(ipntr(2)). | c %----------------------------------------% c call av (comm, nloc, n, workd(ipntr(1)), workd(ipntr(2))) c======== Hack for Linear system ======= ccc call sscal(n, zero, temp, 1) call sscal(n, zero, temp_buf, 1) do 15 j=1,nloc temp_buf(myid*blk + j) = workd(ipntr(2) + j - 1) 15 continue call MPI_ALLREDUCE( temp_buf, temp, n, & MPI_REAL, MPI_SUM, comm, ierr ) call spttrs(n, 1, md, me, temp, n, & ierr) if ( ierr .ne. 0 ) then print*, ' ' print*, ' ERROR with _pttrs. ' print*, ' ' go to 9000 end if do 16 j=1,nloc workd(ipntr(2) + j - 1 ) = temp(myid*blk + j) 16 continue c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c else if ( ido .eq. 2) then c c %-------------------------------------% c | Perform y <--- M*x | c | The matrix vector multiplication | c | routine should take workd(ipntr(1)) | c | as input and return the result to | c | workd(ipntr(2)). | c %-------------------------------------% c call mv (comm, nloc, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call SNAUPD again. | c %-----------------------------------------% c go to 10 c end if c c c %-----------------------------------------% c | Either we have convergence, or there is | c | an error. | c %-----------------------------------------% c if ( info .lt. 0 ) then c c %---------------------------% c | Error message. Check the | c | documentation in PSNAUPD. | c %---------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd.' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using SNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. call psneupd ( comm, rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, nloc, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, & workl, lworkl, ierr ) c c %-----------------------------------------------% c | The real part of the eigenvalue is returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part is returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first NEV | c | columns of the two dimensional array V if | c | requested. Otherwise, an orthogonal basis | c | for the invariant subspace corresponding to | c | the eigenvalues in D is returned in V. | c %-----------------------------------------------% c if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of SNEUPD. | c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd' print *, ' ' endif c else c first = .true. nconv = iparam(5) do 30 j=1, iparam(5) c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*M*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) d(j,3) = psnorm2(comm, nloc, ax, 1) c else if (first) then c c %------------------------% c | Ritz value is complex | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(comm, nloc, n, v(1,j), ax) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j+1), mx) call saxpy(nloc, d(j,2), mx, 1, ax, 1) d(j,3) = psnorm2(comm, nloc, ax, 1)**2 call av(comm, nloc, n, v(1,j+1), ax) call mv(comm, nloc, v(1,j+1), mx) call saxpy(nloc, -d(j,1), mx, 1, ax, 1) call mv(comm, nloc, v(1,j), mx) call saxpy(nloc, -d(j,2), mx, 1, ax, 1) d(j,3) = slapy2( d(j,3), psnorm2(comm,nloc,ax,1) ) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 30 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call psmout(comm, 6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real,Imag) and direct residuals') c end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV3 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program psndrv3. | c %----------------------------% c 9000 continue c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector multiplication subroutine c c Compute the matrix vector multiplication y<---A*x c where A is a n by n nonsymmetric tridiagonal matrix derived c from the central difference discretization of the 1-dimensional c convection diffusion operator on the interval [0,1] with c zero Dirichlet boundary condition. c subroutine av (comm, nloc, n, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, n, j, next, prev Real & v(nloc), w(nloc), one, two, dd, dl, du, & s, h, rho, mv_buf parameter ( rho = 10.0, one = 1.0, & two = 2.0) c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) h = one / real(n+1) s = rho*h / two dd = two dl = -one - s du = -one + s c w(1) = dd*v(1) + du*v(2) do 10 j = 2,nloc-1 w(j) = dl*v(j-1) + dd*v(j) + du*v(j+1) 10 continue w(nloc) = dl*v(nloc-1) + dd*v(nloc) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v(nloc), 1, MPI_REAL, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, 1, MPI_REAL, prev, myid, & comm, status, ierr ) w(1) = w(1) + dl*mv_buf endif c if ( myid .gt. 0 ) then call mpi_send( v(1), 1, MPI_REAL, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, 1, MPI_REAL, next, myid, & comm, status, ierr ) w(nloc) = w(nloc) + du*mv_buf endif c return end c------------------------------------------------------------------------ c c Compute the matrix vector multiplication y<---M*x c where M is a n by n tridiagonal matrix with 4 on the c diagonal, 1 on the subdiagonal and the superdiagonal. c subroutine mv (comm, nloc, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, j, next, prev Real & v(nloc), w(nloc), one, four, mv_buf parameter ( one = 1.0, four = 4.0) c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c w(1) = four*v(1) + one*v(2) do 10 j = 2,nloc-1 w(j) = one*v(j-1) + four*v(j) + one*v(j+1) 10 continue w(nloc) = one*v(nloc-1) + four*v(nloc) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v(nloc), 1, MPI_REAL, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, 1, MPI_REAL, prev, myid, & comm, status, ierr ) w(1) = w(1) + mv_buf endif c if ( myid .gt. 0 ) then call mpi_send( v(1), 1, MPI_REAL, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, 1, MPI_REAL, next, myid, & comm, status, ierr ) w(nloc) = w(nloc) + mv_buf endif c return end c------------------------------------------------------------ subroutine mv2 (comm, n, v, w) integer n, j, comm Real & v(n), w(n) do 10 j=1,n w(j) = v(j) 10 continue c return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pssdrv1.f000066400000000000000000000407631260666001200200660ustar00rootroot00000000000000 program pssdrv1 c c Message Passing Layer: MPI c c Simple program to illustrate the idea of reverse communication c in regular mode for a standard symmetric eigenvalue problem. c c We implement example one of ex-sym.doc in SRC directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is derived from the central difference discretization c of the 2-dimensional Laplacian on the unit square with c zero Dirichlet boundary condition. c ... OP = A and B = I. c ... Assume "call av (n,x,y)" computes y = A*x. c ... Use mode 1 of SSAUPD. c c\BeginLib c c\Routines called: c pssaupd Parallel ARPACK reverse communication interface routine. c psseupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c saxpy Level 1 BLAS that computes y <- alpha*x+y. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sdrv1.F SID: 2.2 c c FILE: sdrv1.F SID: 1.4 DATE OF SID: 3/19/97 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxnloc, maxnev, maxncv, ldv parameter (maxnloc=256, maxnev=10, maxncv=25, & ldv=maxnloc ) c c %--------------% c | Local Arrays | c %--------------% c Real & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxnloc), d(maxncv,2), resid(maxnloc), & ax(maxnloc) logical select(maxncv) integer iparam(11), ipntr(11) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, ierr, j, & nx, nconv, maxitr, mode, ishfts logical rvec Real & tol, sigma c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Real & mv_buf(maxnloc) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Real & psnorm2 external psnorm2, saxpy c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 msaupd = 1 c c %----------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | Laplacian on the unit square with zero Dirichlet | c | boundary condition. The number N(=NX*NX) is the | c | dimension of the matrix. A standard eigenvalue | c | problem is solved (BMAT = 'I'). NEV is the number | c | of eigenvalues to be approximated. The user can | c | modify NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 2 <= NCV <= MAXNCV | c %----------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxnloc ) then print *, ' ERROR with _SDRV1: NLOC is greater than MAXNLOC ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'SM' c c %--------------------------------------------------% c | The work array WORKL is used in PSSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in PSSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero info = 0 ido = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of PSSAUPD is used | c | (IPARAM(7) = 1). All these options may be | c | changed by the user. For details, see the | c | documentation in PSSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine PSSAUPD and take| c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pssaupd ( comm, ido, bmat, nloc, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %--------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine | c | here that takes workd(ipntr(1)) as | c | the input, and return the result to | c | workd(ipntr(2)). | c %--------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call PSSAUPD again.| c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message. Check the | c | documentation in PSSAUPD.| c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _saupd, info = ', info print *, ' Check documentation in _saupd ' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using PSSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call psseupd ( comm, rvec, 'All', select, & d, v, ldv, sigma, & bmat, nloc, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of PSSEUPD.| c %------------------------------------% c c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call saxpy(nloc, -d(j,1), v(1,j), 1, ax, 1) d(j,2) = psnorm2( comm, nloc, ax, 1 ) c 20 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call psmout(comm, 6, nconv, 2, d, maxncv, -6, & 'Ritz values and direct residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_SDRV1 ' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' endif c end if c c %---------------------------% c | Done with program pssdrv1.| c %---------------------------% c 9000 continue c call MPI_FINALIZE(rc) c end c c ------------------------------------------------------------------ c parallel matrix vector subroutine c c The matrix used is the 2 dimensional discrete Laplacian on unit c square with zero Dirichlet boundary condition. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c The subroutine TV is called to computed y<---T*x. c------------------------------------------------------------------- c subroutine av (comm, nloc, nx, mv_buf, v, w) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) integer nloc, nx, np, j, lo, next, prev Real & v(nloc), w(nloc), mv_buf(nx), one parameter (one = 1.0 ) external saxpy call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call saxpy(nx, -one, v(nx+1), 1, w(1), 1) c if ( np .gt. 2) then do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call saxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue end if c if ( np .gt. 1) then lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call saxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) end if c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_REAL, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_REAL, prev, myid, & comm, status, ierr ) call saxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_REAL, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_REAL, next, myid, & comm, status, ierr ) call saxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Real & x(nx), y(nx), dd, dl, du c Real & one parameter (one = 1.0 ) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal. c c dd = 4.0 dl = -one du = -one c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/pzndrv1.f000066400000000000000000000420151260666001200200600ustar00rootroot00000000000000 program pzndrv1 c c Message Passing Layer: MPI c c Example program to illustrate the idea of reverse communication c for a standard complex nonsymmetric eigenvalue problem. c c We implement example one of ex-complex.doc in DOCUMENTS directory c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c in the domain omega = (0,1)x(0,1), with c u = 0 on the boundary of omega. c c ... OP = A and B = I. c ... Assume "call av (comm, nloc, nx, mv_buf, x, y)" computes y = A*x c ... Use mode 1 of PZNAUPD. c c\BeginLib c c\Routines called c pznaupd Parallel ARPACK reverse communication interface routine. c pzneupd Parallel ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a complex vector. c zaxpy Level 1 BLAS that computes y <- alpha*x+y. c av Distributed matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: ndrv1.F SID: 2.1 c c\SCCS Information: c FILE: ndrv1.F SID: 1.1 DATE OF SID: 8/13/96 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c include 'mpif.h' include 'debug.h' include 'stat.h' c c %---------------% c | MPI INTERFACE | c %---------------% integer comm, myid, nprocs, rc, nloc c %-----------------------------% c | Define maximum dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Complex*16 & ax(maxn), d(maxncv), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), resid(maxn), & workl(3*maxncv*maxncv+5*maxncv) Double precision & rwork(maxncv), rd(maxncv,3) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, j, & ierr, nconv, maxitr, ishfts, mode Complex*16 & sigma Double precision & tol logical rvec c c %----------------------------------------------% c | Local Buffers needed for MPI communication | c %----------------------------------------------% c Complex*16 & mv_buf(maxn) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & pdznorm2 external pdznorm2, zaxpy c c %-----------------------% c | Executable Statements | c %-----------------------% c call MPI_INIT( ierr ) comm = MPI_COMM_WORLD call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c ndigit = -3 logfil = 6 mcaupd = 1 c c %--------------------------------------------------% c | The number NX is the number of interior points | c | in the discretization of the 2-dimensional | c | convection-diffusion operator on the unit | c | square with zero Dirichlet boundary condition. | c | The number N(=NX*NX) is the dimension of the | c | matrix. A standard eigenvalue problem is | c | solved (BMAT = 'I'). NEV is the number of | c | eigenvalues to be approximated. The user can | c | modify NX, NEV, NCV, WHICH to solve problems of | c | different sizes, and to get different parts of | c | the spectrum. However, The following | c | conditions must be satisfied: | c | N <= MAXN | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c %--------------------------------------------------% c nx = 10 n = nx*nx nev = 4 ncv = 20 c c %--------------------------------------% c | Set up distribution of data to nodes | c %--------------------------------------% c nloc = (nx / nprocs)*nx if ( mod(nx, nprocs) .gt. myid ) nloc = nloc + nx c if ( nloc .gt. maxn ) then print *, ' ERROR with _NDRV1: NLOC is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NDRV1: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NDRV1: NCV is greater than MAXNCV ' go to 9000 end if bmat = 'I' which = 'LM' c c %---------------------------------------------------% c | The work array WORKL is used in ZNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication, and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated to start the ARNOLDI iteration. | c %---------------------------------------------------% c lworkl = 3*ncv**2+5*ncv tol = 0.0 ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shift with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of ZNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | ZNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 1 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine ZNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call pznaupd ( comm, ido, bmat, nloc, which, & nev, tol, resid, ncv, v, ldv, iparam, ipntr, & workd, workl, lworkl, rwork,info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- OP*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av ( comm, nloc, nx, mv_buf, & workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call ZNAUPD again. | c %-----------------------------------------% c go to 10 end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in ZNAUPD | c %--------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _naupd, info = ', info print *, ' Check the documentation of _naupd' print *, ' ' endif c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using ZNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .true. c call pzneupd (comm, rvec, 'A', select, d, v, ldv, sigma, & workev, bmat, nloc, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & rwork, ierr) c c %----------------------------------------------% c | Eigenvalues are returned in the one | c | dimensional array D. The corresponding | c | eigenvectors are returned in the first NCONV | c | (=IPARAM(5)) columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of ZNEUPD. | c %------------------------------------% c if ( myid .eq. 0 ) then print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' endif c else c nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c call av(comm, nloc, nx, mv_buf, v(1,j), ax) call zaxpy(nloc, -d(j), v(1,j), 1, ax, 1) rd(j,1) = dble(d(j)) rd(j,2) = dimag(d(j)) rd(j,3) = pdznorm2(comm, nloc, ax, 1) c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call pdmout(comm, 6, nconv, 3, rd, maxncv, -6, & 'Ritz values (Real, Imag) and direct residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if (myid .eq. 0)then if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit & Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, '_NDRV1' print *, '====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of processors is ', nprocs print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c endif end if c c %----------------------------% c | Done with program pzndrv1. | c %----------------------------% c 9000 continue c c c %-------------------------% c | Release resources MPI | c %-------------------------% c call MPI_FINALIZE(rc) c end c c========================================================================== c c parallel matrix vector subroutine c c The matrix used is the convection-diffusion operator c discretized using centered difference. c c Computes w <--- OP*v, where OP is the nx*nx by nx*nx block c tridiagonal matrix c c | T -I | c |-I T -I | c OP = | -I T | c | ... -I| c | -I T| c c derived from the standard central difference discretization c of the convection-diffusion operator (Laplacian u) + rho*(du/dx) c with zero boundary condition. c c The subroutine TV is called to computed y<---T*x. c c---------------------------------------------------------------------------- subroutine av (comm, nloc, nx, mv_buf, v, w ) c c .. MPI Declarations ... include 'mpif.h' integer comm, nprocs, myid, ierr, & status(MPI_STATUS_SIZE) c integer nloc, nx, np, j, lo, next, prev Complex*16 & v(nloc), w(nloc), mv_buf(nx), one parameter (one = (1.0, 0.0)) external zaxpy, tv c call MPI_COMM_RANK( comm, myid, ierr ) call MPI_COMM_SIZE( comm, nprocs, ierr ) c np = nloc/nx call tv(nx,v(1),w(1)) call zaxpy(nx, -one, v(nx+1), 1, w(1), 1) c do 10 j = 2, np-1 lo = (j-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) call zaxpy(nx, -one, v(lo+nx+1), 1, w(lo+1), 1) 10 continue c lo = (np-1)*nx call tv(nx, v(lo+1), w(lo+1)) call zaxpy(nx, -one, v(lo-nx+1), 1, w(lo+1), 1) c next = myid + 1 prev = myid - 1 if ( myid .lt. nprocs-1 ) then call mpi_send( v((np-1)*nx+1), nx, MPI_DOUBLE_COMPLEX, & next, myid+1, comm, ierr ) endif if ( myid .gt. 0 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_COMPLEX, prev, myid, & comm, status, ierr ) call zaxpy( nx, -one, mv_buf, 1, w(1), 1 ) endif c if ( myid .gt. 0 ) then call mpi_send( v(1), nx, MPI_DOUBLE_COMPLEX, & prev, myid-1, comm, ierr ) endif if ( myid .lt. nprocs-1 ) then call mpi_recv( mv_buf, nx, MPI_DOUBLE_COMPLEX, next, myid, & comm, status, ierr ) call zaxpy( nx, -one, mv_buf, 1, w(lo+1), 1 ) endif c return end c========================================================================= subroutine tv (nx, x, y) c integer nx, j Complex*16 & x(nx), y(nx), h, dd, dl, du c Complex*16 & one, rho parameter (one = (1.0, 0.0), rho = (100.0, 0.0)) c c Compute the matrix vector multiplication y<---T*x c where T is a nx by nx tridiagonal matrix with DD on the c diagonal, DL on the subdiagonal, and DU on the superdiagonal c h = one / dcmplx(nx+1) dd = (4.0, 0.0) dl = -one - (0.5, 0.0)*rho*h du = -one + (0.5, 0.0)*rho*h c y(1) = dd*x(1) + du*x(2) do 10 j = 2,nx-1 y(j) = dl*x(j-1) + dd*x(j) + du*x(j+1) 10 continue y(nx) = dl*x(nx-1) + dd*x(nx) return end arpack-ng-3.3.0/PARPACK/EXAMPLES/MPI/stat.h000066400000000000000000000017131260666001200174310ustar00rootroot00000000000000c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c c\SCCS Information: @(#) c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2 c real t0, t1, t2, t3, t4, t5 save t0, t1, t2, t3, t4, t5 c integer nopx, nbx, nrorth, nitref, nrstrt real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec common /timing/ & nopx, nbx, nrorth, nitref, nrstrt, & tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec arpack-ng-3.3.0/PARPACK/Makefile.am000066400000000000000000000010611260666001200164720ustar00rootroot00000000000000SUBDIRS = UTIL SRC . EXAMPLES/MPI EXAMPLES/BLACS lib_LTLIBRARIES = libparpack.la libparpack_la_SOURCES = # Force libparpack to be linked with the MPI Fortran compiler. # The file dummy.f does not need to exist in the source tree. F77 = $(MPIF77) nodist_EXTRA_libparpack_la_SOURCES = dummy.f libparpack_la_LDFLAGS = -no-undefined -version-info 2:0 libparpack_la_LIBADD = \ $(top_builddir)/PARPACK/SRC/MPI/libparpacksrcmpi.la \ $(top_builddir)/PARPACK/UTIL/MPI/libparpackutilmpi.la \ $(top_builddir)/libarpack.la \ $(LAPACK_LIBS) $(BLAS_LIBS) $(MPILIBS) arpack-ng-3.3.0/PARPACK/SRC/000077500000000000000000000000001260666001200150675ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/SRC/BLACS/000077500000000000000000000000001260666001200157135ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/SRC/BLACS/Makefile.am000066400000000000000000000014061260666001200177500ustar00rootroot00000000000000SSRC = psnaitr.f psnapps.f psnaup2.f psnaupd.f psneigh.f psneupd.f psngets.f \ pssaitr.f pssapps.f pssaup2.f pssaupd.f psseigt.f psseupd.f pssgets.f \ psgetv0.f pslamch.f pslarnv.f psnorm2.f DSRC = pdnaitr.f pdnapps.f pdnaup2.f pdnaupd.f pdneigh.f pdneupd.f pdngets.f \ pdsaitr.f pdsapps.f pdsaup2.f pdsaupd.f pdseigt.f pdseupd.f pdsgets.f \ pdgetv0.f pdlamch.f pdlarnv.f pdnorm2.f CSRC = pcnaitr.f pcnapps.f pcnaup2.f pcnaupd.f pcneigh.f pcneupd.f pcngets.f \ pcgetv0.f pclarnv.f pscnorm2.f ZSRC = pznaitr.f pznapps.f pznaup2.f pznaupd.f pzneigh.f pzneupd.f pzngets.f \ pzgetv0.f pzlarnv.f pdznorm2.f EXTRA_DIST = debug.h stat.h noinst_LTLIBRARIES = libparpacksrc.la libparpacksrc_la_SOURCES = $(SSRC) $(DSRC) $(CSRC) $(ZSRC) arpack-ng-3.3.0/PARPACK/SRC/BLACS/debug.h000066400000000000000000000013511260666001200171520ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcgetv0.f000066400000000000000000000345361260666001200174450ustar00rootroot00000000000000c\BeginDoc c c\Name: pcgetv0 c c Message Passing Layer: BLACS c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pcgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pcgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pcgetv0 is called. c It should be set to 1 on the initial call to pcgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Complex work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c pcvout Parallel ARPACK utility routine that prints vectors. c pclarnv Parallel wrapper for LAPACK routine clarnv (generates a random vector). c cgemv Level 2 BLAS routine for matrix vector multiplication. c ccopy Level 1 BLAS that copies one vector to another. c cdotc Level 1 BLAS that computes the scalar product of two vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: getv0.F SID: 2.1 c c\SCCS Information: c FILE: getv0.F SID: 1.7 DATE OF SID: 04/12/01 c c\EndLib c c----------------------------------------------------------------------- c subroutine pcgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm, nprow, npcol, myprow, mypcol external cgsum2d, blacs_gridinfo c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) , & rzero = 0.0 ) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj, myid, igen Real & rnorm0 Complex & cnorm, cnorm2 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, cgemv, pclarnv, pcvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & pscnorm2, slapy2 Complex & cdotc external cdotc, pscnorm2, slapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then c c %-----------------------------------% c | Generate a seed on each processor | c | using process id (myid). | c | Note: the seed must be between 1 | c | and 4095. iseed(4) must be odd. | c %-----------------------------------% c call BLACS_GRIDINFO(comm, nprow, npcol, myprow, mypcol) c c %-------------------------------------------% c | Convert a 2-D process id (myprow, mypcol) | c | to a 1-D process id (myid). | c %-------------------------------------------% c myid = npcol*myprow + mypcol + 1 igen = 1000 + 2*myid - 1 if (igen .gt. 4095) then write(0,*) 'Error in p_getv0: seed exceeds 4095!' end if c iseed(1) = igen/1000 igen = mod(igen,1000) iseed(2) = igen/100 igen = mod(igen,100) iseed(3) = igen/10 iseed(4) = mod(igen,10) c inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pclarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call ccopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd, 1) call cgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm0 = sqrt(slapy2(real (cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm0 = pscnorm2( comm, n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett`s book, page 107 and in Gragg and Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call cgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workl, 1) call cgsum2d( comm, 'All', ' ', j-1, 1, workl, j, -1, -1 ) call cgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd, 1) call cgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm = sqrt(slapy2(real (cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5 ) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then cnorm2 = cmplx(rnorm,rzero) call pcvout (comm, logfil, 1, cnorm2, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pcvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pcgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pclarnv.f000066400000000000000000000036241260666001200175340ustar00rootroot00000000000000c\BeginDoc c c\Name: pclarnv c c Message Passing Layer: BLACS c c\Description: c c Parallel Version of ARPACK utility routine clarnv c c PCLARNV returns a vector of n (nloc) random Complex numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM BLACS Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Complex array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine clarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine CLARNV to generate random c Complex numbers from a uniform or normal distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.3 DATE OF SID: 04/17/99 c c----------------------------------------------------------------------- c subroutine pclarnv( comm, idist, iseed, n, x ) c integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Complex & x( * ) c .. c .. External Subroutines .. external clarnv c .. c .. Executable Statements .. c call clarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcnaitr.f000066400000000000000000000765051260666001200175370ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pcnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pcnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pcnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Complex work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pcgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c clanhs LAPACK routine that computes various norms of a matrix. c clascl LAPACK routine for careful scaling of a matrix. c slabad LAPACK routine for defining the underflow and overflow c limits c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of c two vectors. c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c pscnorm2 Parallel version of Level 1 BLAS that computes the c norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: naitr.F SID: 2.1 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pcnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external cgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone, rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0, rzero = 0.0) c c %--------------% c | Local Arrays | c %--------------% c Real & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cscal, cgemv, pcgetv0, slabad, & csscal, pcvout, pcmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex & cdotc Real & pslamch, pscnorm2, clanhs, slapy2 external cdotc, pscnorm2, clanhs, pslamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------% c unfl = pslamch(comm, 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pcgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pcvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pcgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call ccopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call csscal (n, temp1, v(1,j), 1) call csscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine clascl | c %-----------------------------------------% c call clascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call clascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call ccopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call ccopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) call cgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) wnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = pscnorm2(comm, n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) call cgsum2d( comm, 'All', ' ', j, 1, h(1,j), j, -1, -1 ) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = cmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) call cgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call psvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call pcvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call cgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call caxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) call cgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm1 = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = pscnorm2(comm, n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call psvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %--------------------------------------------% c tst1 = slapy2(real(h(i,i)),aimag(h(i,i))) & + slapy2(real(h(i+1,i+1)), aimag(h(i+1,i+1))) if( tst1.eq.real(zero) ) & tst1 = clanhs( '1', k+np, h, ldh, workd(n+1) ) if( slapy2(real(h(i+1,i)),aimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pcmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pcnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcnapps.f000066400000000000000000000431061260666001200175320ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnapps c c Message Passing Layer: BLACS c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pcnapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex array of length NP. (INPUT) c The shifts to be applied. c c V Complex N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clanhs LAPACK routine that computes various norms of a matrix. c clartg LAPACK Givens rotation construction routine. c claset LAPACK matrix initialization routine. c slabad LAPACK routine for defining the underflow and overflow c limits. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another. c cscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: napps.F SID: 2.1 c c\SCCS Information: c FILE: napps.F SID: 1.4 DATE OF SID: 10/25/03 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine clahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex & cdum, f, g, h11, h21, r, s, sigma, t Real & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cgemv, cscal, clacpy, clartg, & pcvout, claset, slabad, pcmout, arscnd, pivout c c %--------------------% c | External Functions | c %--------------------% c Real & clanhs, pslamch, slapy2 external clanhs, pslamch, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, aimag, conjg, cmplx, max, min, real c c %---------------------% c | Statement Functions | c %---------------------% c Real & cabs1 cabs1( cdum ) = abs( real( cdum ) ) + abs( aimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------------% c unfl = pslamch( 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = slamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call claset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pcvout (comm, logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %----------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = clanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(real(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pcvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call clartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( real( h(j+1,j) ) .lt. rzero .or. & aimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / slapy2(real(h(j+1,j)),aimag(h(j+1,j))) call cscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call cscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call cscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = cmplx( real( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = clanhs( '1', kev, h, ldh, workl ) if( real( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call cgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call cgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call ccopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call clacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call ccopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call cscal (n, q(kplusp,kev), resid, 1) if ( real( h(kev+1,kev) ) .gt. rzero ) & call caxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pcvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pcvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pcmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %----------------% c | End of pcnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcnaup2.f000066400000000000000000000722411260666001200174400ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by pcnaupd. c c\Usage: c call pcnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pcnaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pcnaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in PCNAUPD. c c RWORK Real work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pcgetv0 Parallel ARPACK initial vector generation routine. c pcnaitr Parallel ARPACK Arnoldi factorization routine. c pcnapps Parallel ARPACK application of implicit shifts routine. c pcneigh Parallel ARPACK compute Ritz values and error bounds routine. c pcngets Parallel ARPACK reorder Ritz values and error bounds routine. c csortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c psvout ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of two vectors. c cswap Level 1 BLAS that swaps two vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c FILE: naup2.F SID: 1.7 DATE OF SID: 10/25/03 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external cgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Real & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm, getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex & cmpnorm Real & rnorm, eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0, eps23 c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, pcgetv0, pcnaitr, pcneigh, pcngets, pcnapps, & csortc, cswap, pcmout, pcvout, pivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex & cdotc Real & pscnorm2, pslamch, slapy2 external cdotc, pscnorm2, pslamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real, min, max, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pcgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pcnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pcnapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pcnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pcneigh ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from pcneigh. | c %--------------------------------------------------% c call ccopy(kplusp,ritz,1,workl(kplusp**2+1),1) call ccopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call pcngets ( comm, ishift, which, nev, np, ritz, & bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, slapy2( real(ritz(np+i)), & aimag(ritz(np+i)) ) ) if ( slapy2(real(bounds(np+i)),aimag(bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call pcvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call pcvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call pcvout(comm, logfil, kplusp, & workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call pcvout(comm, logfil, kplusp, & workl(kplusp**2+kplusp+1), ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to pcneupd if needed | c %------------------------------------------% c h(3,1) = cmplx(rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call csortc(wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, slapy2( real(ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call csortc(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, slapy2( real(ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call csortc(which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call pcvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call pcvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pcngets (comm, ishift, which, nev, np, ritz, & bounds) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pcvout (comm, logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call pcvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call ccopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pcvout (comm, logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call pcvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pcnapps(comm, n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pcnaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm = cdotc (n, resid, 1, workd, 1) call cgsum2d( comm, 'All', ' ', 1, 1, cmpnorm, 1, -1, -1 ) rnorm = sqrt(slapy2(real(cmpnorm),aimag(cmpnorm))) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pcmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pcnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcnaupd.f000066400000000000000000000674251260666001200175320ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaupd c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then ssaupd or snaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pcnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pcnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pcnaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pcnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = pslamch(comm, 'EPS') (machine precision as computed c by the ScaLAPACK auxiliary subroutine pslamch). c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below) c c V Complex array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of pcnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by pcneupd. See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c cneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Real work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine pcneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call pcneupd immediately following c completion of pcnaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pcnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c cstatn ARPACK routine that initializes the timing variables. c pivout Parallel ARPACK utility routine that prints integers. c pcvout Parallel ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c pslamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, rwork, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Real & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pcnaup2, pcvout, pivout, arscnd, cstatn c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call cstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0 ) tol = pslamch(comm, 'EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine pcneigh called | c | by pcnaup2. Subroutine pcneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pcnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pcnaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pcvout (comm, logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call pcvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pcnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcneigh.f000066400000000000000000000205351260666001200175040ustar00rootroot00000000000000c\BeginDoc c c\Name: pcneigh c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pcneigh c ( COMM, RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Real work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from clahqr or ctrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c psvout Parallel ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c ccopy Level 1 BLAS that copies one vector to another. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: neigh.F SID: 2.1 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pcneigh (comm, rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Real & rwork(n) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex & vl(1) Real & temp c c %----------------------% c | External Subroutines | c %----------------------% c external clacpy, clahqr, csscal, ctrevc, ccopy, & pcmout, pcvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2 external scnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call pcmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | clahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call clacpy ('All', n, n, h, ldh, workl, n) call claset ('All', n, n, zero, one, q, ldq) call clahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call ccopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call pcvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ctrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = scnrm2( n, q(1,j), 1 ) call csscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call ccopy(n, q(n,1), ldq, workl, 1) call pcvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call ccopy(n, q(n,1), n, bounds, 1) call csscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call pcvout (comm, logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call pcvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pcneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcneupd.f000066400000000000000000001046541260666001200175320ustar00rootroot00000000000000c\BeginDoc c c\Name: pcneupd c c Message Passing Layer: BLACS c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PCNAUPD. PCNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of PCNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of PCNAUPD. c c\Usage: c call pcneupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PCNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PCNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to CNEUPD following the last call c to PCNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PCNAUPD and the call to CNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PCNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c PCNAUPD. They are not changed by PCNEUPD. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by PCNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PCNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ctrsen. c Re-enter subroutine pcneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ctrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PCNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: CNEUPD got a different count of the number of converged c Ritz values than CNAUPD got. This indicates the user c probably made an error in passing data from CNAUPD to c CNEUPD or that the data was modified before entering c CNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c cgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ctrsen LAPACK routine that re-orders the Schur form. c cunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c pslamch ScaLAPACK routine that determines machine constants. c ctrmm Level 3 BLAS matrix times an upper triangular matrix. c cgeru Level 2 BLAS rank one update to a matrix. c ccopy Level 1 BLAS that copies one vector to another . c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: neupd.F SID: 2.2 c c\SCCS Information: c FILE: neupd.F SID: 1.9 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pcneupd & ( comm , rvec , howmny, select, d , & z , ldz , sigma , workev, bmat , & n , which , nev , tol , resid, & ncv , v , ldv , iparam, ipntr, & workd, workl , lworkl, rwork , info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex & sigma Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & rwork(ncv) Complex & d(nev) , resid(n) , v(ldv,ncv) , & z(ldz, nev), workd(3*n), workl(lworkl), & workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift Complex & rnorm, temp, vl(1) Real & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy ,cgeru,cgeqr2,clacpy,pcmout, & cunm2r,ctrmm,pcvout,pivout, & clahqr c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2,pslamch,slapy2 external scnrm2,pslamch,slapy2 c Complex & cdotc external cdotc c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by CNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pcvout(comm, logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call pcvout(comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pcngets(comm, ishift, which , & nev , np , workl(irz), & workl(bounds)) c if (msglvl .gt. 2) then call pcvout(comm,logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call pcvout(comm,logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & slapy2 ( real (workl(irz+ncv-j)), & aimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & slapy2( real (workl(ibd+jj-1)), & aimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine clahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by PCNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call ccopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call claset('All', ncv, ncv, zero, one, workl(invsub), ldq) call clahqr(.true. , .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr ) call ccopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pcvout(comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call pcvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pcmout(comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ctrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv , conds , sep , & workev, ncv, ierr) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pcvout (comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call pcmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call ccopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call ccopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call cgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using cunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call cunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call clacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( real( workl(invsub+(j-1)*ldq+j-1) ) .lt. & real(zero) ) then call cscal(nconv, -one, workl(iuptri+j-1), ldq) call cscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ctrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr ) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = scnrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = real(one) / rtemp call csscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = cdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call ccopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call pcvout(comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pcmout(comm, logfil, nconv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call ccopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ctrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PCNAUPD into D. | c %--------------------------------------------------% c call ccopy(nconv, workl(ritz), 1, d, 1) call ccopy(nconv, workl(ritz), 1, workl(iheig), 1) call ccopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pcvout (comm, logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call pcvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call pcvout (comm, logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call pcvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call cgeru(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of pcneupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pcngets.f000066400000000000000000000134741260666001200175360ustar00rootroot00000000000000c\BeginDoc c c\Name: pcngets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pcngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c csortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcvout Parallel ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: ngets.F SID: 2.1 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine pcngets ( comm, ishift, which, kev, np, ritz, bounds) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external pcvout, csortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call csortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pcnapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call csortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pcvout (comm, logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call pcvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pcngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdgetv0.f000066400000000000000000000332711260666001200174410ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdgetv0 c c Message Passing Layer: BLACS c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pdgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pdgetv0 is called. c It should be set to 1 on the initial call to pdgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Double precision N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Double precision work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine for vector output. c pdlarnv Parallel wrapper for LAPACK routine dlarnv (generates a random vector). c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: getv0.F SID: 2.3 c c\SCCS Information: c FILE: getv0.F SID: 1.4 DATE OF SID: 3/19/97 c c\EndLib c c----------------------------------------------------------------------- c subroutine pdgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Double precision & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external pdlarnv, pdvout, dcopy, dgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2 external ddot, pdnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pdlarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call dcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c first = .FALSE. if (bmat .eq. 'G') then rnorm0 = ddot (n, resid, 1, workd, 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm0, 1, -1, -1 ) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = pdnorm2( comm, n, resid, 1 ) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call dgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workl, 1) call dgsum2d( comm, 'All', ' ', j-1, 1, workl, j, -1, -1 ) call dgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pdvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdlamch.f000066400000000000000000000050761260666001200175020ustar00rootroot00000000000000 DOUBLE PRECISION FUNCTION PDLAMCH( ICTXT, CMACH ) * * -- ScaLAPACK auxilliary routine (version 1.0) -- * University of Tennessee, Knoxville, Oak Ridge National Laboratory, * and University of California, Berkeley. * February 28, 1995 * * .. Scalar Arguments .. CHARACTER CMACH INTEGER ICTXT * .. * * Purpose * ======= * * PDLAMCH determines double precision machine parameters. * * Arguments * ========= * * ICTXT (global input) INTEGER * The BLACS context handle in which the computation takes * place. * * CMACH (global input) CHARACTER*1 * Specifies the value to be returned by PDLAMCH: * = 'E' or 'e', PDLAMCH := eps * = 'S' or 's , PDLAMCH := sfmin * = 'B' or 'b', PDLAMCH := base * = 'P' or 'p', PDLAMCH := eps*base * = 'N' or 'n', PDLAMCH := t * = 'R' or 'r', PDLAMCH := rnd * = 'M' or 'm', PDLAMCH := emin * = 'U' or 'u', PDLAMCH := rmin * = 'L' or 'l', PDLAMCH := emax * = 'O' or 'o', PDLAMCH := rmax * * where * * eps = relative machine precision * sfmin = safe minimum, such that 1/sfmin does not overflow * base = base of the machine * prec = eps*base * t = number of (base) digits in the mantissa * rnd = 1.0 when rounding occurs in addition, 0.0 otherwise * emin = minimum exponent before (gradual) underflow * rmin = underflow threshold - base**(emin-1) * emax = largest exponent before overflow * rmax = overflow threshold - (base**emax)*(1-eps) * * ===================================================================== * * .. Local Scalars .. INTEGER IDUMM DOUBLE PRECISION TEMP * .. * .. External Subroutines .. EXTERNAL DGAMN2D, DGAMX2D * .. * .. External Functions .. LOGICAL LSAME DOUBLE PRECISION DLAMCH EXTERNAL DLAMCH, LSAME * .. * .. Executable Statements .. * TEMP = DLAMCH( CMACH ) * IF( LSAME( CMACH, 'E' ).OR.LSAME( CMACH, 'S' ).OR. $ LSAME( CMACH, 'M' ).OR.LSAME( CMACH, 'U' ) ) THEN CALL DGAMX2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, $ IDUMM, 1, -1, IDUMM ) ELSE IF( LSAME( CMACH, 'L' ).OR.LSAME( CMACH, 'O' ) ) THEN CALL DGAMN2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, $ IDUMM, 1, -1, IDUMM ) END IF * PDLAMCH = TEMP * * End of PDLAMCH * END arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdlarnv.f000066400000000000000000000040001260666001200175220ustar00rootroot00000000000000c\BeginDoc c c\Name: pdlarnv c c Message Passing Layer: BLACS c c\Description: c c Parallel Version of ARPACK utility routine dlarnv c c PSLARNV returns a vector of n (nloc) random real numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM BLACS Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Double precision array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine dlarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine SLARNV to generate random c real numbers from a uniform (0,1) distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.4 DATE OF SID: 04/16/99 c c----------------------------------------------------------------------- c subroutine pdlarnv( comm, idist, iseed, n, x ) c c .. BLACS VARIABLES AND FUNCTIONS .. integer comm c c .. External Functions .. external BLACS_GRIDINFO c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Double precision & x( * ) c .. c .. External Subroutines .. external dlarnv c .. c .. Executable Statements .. c call dlarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdnaitr.f000066400000000000000000000756141260666001200175400ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdnaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pdnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pdnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pdnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pdgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout Parallel ARPACK utility routine that prints vectors. c dlabad LAPACK routine that computes machine constants. c pdlamch ScaLAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dlanhs LAPACK routine that computes various norms of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naitr.F SID: 2.2 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pdnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, pdgetv0, dlabad, & pdvout, pdmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, dlanhs, pdlamch external ddot, pdnorm2, dlanhs, pdlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------% c unfl = pdlamch(comm, 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = pdlamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pdgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pdgetv0 ( comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then wnorm = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) call dgsum2d( comm, 'All', ' ', j, 1, h(1,j), j, -1, -1 ) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call pdvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call dgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call daxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm1, 1, -1, -1 ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = pdnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pdmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pdnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdnapps.f000066400000000000000000000562341260666001200175410ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdnapps c c Message Passing Layer: BLACS c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pdnapps c ( COMM, N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Double precision array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to pdnapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c dlabad LAPACK routine that computes machine constants. c dlacpy LAPACK matrix copy routine. c pdlamch ScaLAPACK routine that determines machine constants. c dlanhs LAPACK routine that computes various norms of a matrix. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlarf LAPACK routine that applies Householder reflection to c a matrix. c dlarfg LAPACK Householder reflection construction routine. c dlartg LAPACK Givens rotation construction routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another . c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: napps.F SID: 2.2 c c\SCCS Information: c FILE: napps.F SID: 1.5 DATE OF SID: 03/19/97 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine dlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnapps & ( comm, n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, & q, ldq, workl, workd ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Double precision & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlarf, dlarfg, dlartg, & dlaset, dlabad, arscnd, pivout, pdvout, pdmout c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch, dlanhs, dlapy2 external pdlamch, dlanhs, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------------% c unfl = pdlamch( comm, 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = pdlamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pdvout (comm, logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call pdvout (comm, logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pdvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call dlartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = dlapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call dlarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call dlarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call dlarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call dlarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call dscal( kplusp-j+1, -one, h(j+1,j), ldh ) call dscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call dscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %---------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %---------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call daxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pdvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pdmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %----------------% c | End of pdnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdnaup2.f000066400000000000000000000771441260666001200174500ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by pdnaupd . c c\Usage: c call pdnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pdnaupd . c MODE, ISHIFT, MXITER: see the definition of IPARAM in pdnaupd . c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from dneigh . c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pdgetv0 Parallel ARPACK initial vector generation routine. c pdnaitr Parallel ARPACK Arnoldi factorization routine. c pdnapps Parallel ARPACK application of implicit shifts routine. c dnconv ARPACK convergence of Ritz values routine. c pdneigh Parallel ARPACK compute Ritz values and error bounds routine. c pdngets Parallel ARPACK reorder Ritz values and error bounds routine. c dsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Revision history: c Starting Point: Serial Code FILE: naup2.F SID: 2.2 c c\SCCS Information: c FILE: naup2.F SID: 1.5 DATE OF SID: 06/01/00 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Double precision & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv, & j Double precision & rnorm , temp , eps23 save cnorm , getv0, initv , update, ushift, & rnorm , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , eps23 , numcnv c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , pdgetv0 , pdnaitr , dnconv , & pdneigh , pdngets , pdnapps , & pdvout , pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot , pdnorm2 , dlapy2 , pdlamch external ddot , pdnorm2 , dlapy2 , pdlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = pdlamch (comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pdgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pdnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pdnapps . | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pdnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pdneigh ( comm, rnorm, kplusp, h, ldh, ritzr, ritzi, & bounds, q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from pdneigh . | c %----------------------------------------------------% c call dcopy (kplusp, ritzr, 1, workl(kplusp**2+1), 1) call dcopy (kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call dcopy (kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of pdngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call pdngets ( comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call dnconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call pivout (comm, logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call pdvout (comm, logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call pdvout (comm, logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call dvout (logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with dngets , we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in dngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call dsortc (wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call dsortc (which, .true., nconv, ritzr, ritzi, bounds) c c if (msglvl .gt. 1) then call dvout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call dvout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call dvout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pdngets (comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pdvout (comm, logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call pdvout (comm, logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call pdvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call dcopy (np, workl, 1, ritzr, 1) call dcopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pdvout (comm, logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call pdvout (comm, logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call pdvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pdnapps (comm, n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pdnaitr . | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) call dgsum2d ( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2 ( comm, n, resid, 1 ) end if cnorm = .false. c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pdmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pdnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdnaupd.f000066400000000000000000000734401260666001200175250ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnaupd c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine dsaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pdnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pdnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdnaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pdnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Double precision array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of pdnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pdnaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by dneupd . See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c pdneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine dneupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine dneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call dneupd immediately following c completion of pdnaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Double precision resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Double precision resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pdnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.9 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external pdnaup2 , pdvout , pivout, arscnd, dstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch external pdlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pdlamch (comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine pdneigh called | c | by pdnaup2 . Subroutine dneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pdnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pdnaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pdvout (comm, logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call pdvout (comm, logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call pdvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pdnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdneigh.f000066400000000000000000000251541260666001200175070ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdneigh c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pdneigh c ( COMM, RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Double precision N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Double precision N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from dlahqr or dtrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dlahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dlacpy LAPACK matrix copy routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another . c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neigh.F SID: 2.2 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdneigh ( comm, rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Double precision & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dlacpy, dlahqr, dtrevc, dvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call pdmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | dlahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call dlacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = 1 call dlahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call dtrevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = dnrm2( n, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2( dnrm2( n, q(1,i), 1 ), & dnrm2( n, q(1,i+1), 1 ) ) call dscal ( n, one / temp, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call dgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * dlapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call pdvout (comm, logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call pdvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdneupd.f000066400000000000000000001270611260666001200175300ustar00rootroot00000000000000c\BeginDoc c c\Name: pdneupd c c Message Passing Layer: BLACS c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PDNAUPD . PDNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine PDNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of PDNAUPD . c c\Usage: c call pdneupd c ( COMM, RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Double precision array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c PDNAUPD . A further computation must be performed by the user c to transform the Ritz values computed for OP by PDNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Double precision array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Double precision N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PDNAUPD . In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Double precision work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PDNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PDNEUPD following the last call c to PDNAUPD . These arguments MUST NOT BE MODIFIED between c the the last call to PDNAUPD and the call to PDNEUPD . c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Double precision N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PDNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c PDNAUPD . They are not changed by PDNEUPD . c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointers into WORKL for addresses c of the above information computed by PDNEUPD . c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PDNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine dlahqr c could not be reordered by LAPACK routine dtrsen . c Re-enter subroutine pdneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine dlahqr . c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine dtrevc . c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PDNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: PDNEUPD got a different count of the number of converged c Ritz values than PDNAUPD got. This indicates the user c probably made an error in passing data from PDNAUPD to c PDNEUPD or that the data was modified before entering c PDNEUPD . c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout Parallel ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c dlahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c pdlamch ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK matrix initialization routine. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c dtrsen LAPACK routine that re-orders the Schur form. c dtrmm Level 3 BLAS matrix times an upper triangular matrix. c dger Level 2 BLAS rank one update to a matrix. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X` denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by PDNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c Z(:,I)` * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c Z(:,I)` * A * Z(:,I) + Z(:,I+1)` * A * Z(:,I+1), c Z(:,I)` * A * Z(:,I+1) - Z(:,I+1)` * A * Z(:,I), respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute V(:,1:IPARAM(5))` * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neupd.F SID: 2.3 c c\SCCS Information: c FILE: neupd.F SID: 1.8 DATE OF SID: 04/10/01 c c\EndLib c c----------------------------------------------------------------------- subroutine pdneupd & (comm , rvec , howmny, select, dr , di , & z , ldz , sigmar, sigmai, workev, bmat, & n , which, nev , tol , resid , & ncv , v , ldv , iparam, ipntr , & workd, workl, lworkl, info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & dr(nev+1) , di(nev+1) , resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr, ih, ihbds, & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj logical reord Double precision & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2 , dlacpy , & dlahqr , dlaset , pdmout , dorm2r , & dtrevc , dtrmm , dtrsen , dscal , & pdvout , pivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2 , dnrm2 , pdlamch external dlapy2 , dnrm2 , pdlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch (comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by PDNEUPD . | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call pdvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call pdvout (comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pdngets (comm , ishift , which , & nev , np , workl(irr), & workl(iri), workl(bounds), & workl , workl(np+1)) c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call pdvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call pdvout (comm, logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & dlapy2 ( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine dlahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by PDNAUPD . | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ldh*ncv, workl(ih), 1, workl(iuptri), 1) call dlaset ('All', ncv, ncv, zero, one, workl(invsub), ldq) call dlahqr (.true. , .true. , ncv, 1 , & ncv , workl(iuptri), ldh, workl(iheigr), & workl(iheigi), 1 , ncv, workl(invsub), & ldq , ierr) call dcopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pdvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call pdvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call pdvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call dtrsen ('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheigr), & workl(iheigi), nconv , conds , & sep , workl(ihbds) , ncv , & iwork , 1 , ierr ) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call pdvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call dcopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using dorm2r . | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call dlacpy ('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call dscal (nconv, -one, workl(iuptri+j-1), ldq) call dscal (nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call dtrevc ('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = dnrm2 ( ncv, workl(invsub+(j-1)*ldq), 1 ) call dscal ( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2 (dnrm2 (ncv, & workl(invsub+(j-1)*ldq), & 1 ), & dnrm2 (ncv, & workl(invsub+j*ldq), & 1) & ) call dscal (ncv, one/temp, & workl(invsub+(j-1)*ldq), 1) call dscal (ncv, one/temp, & workl(invsub+j*ldq), 1) iconj = 1 else iconj = 0 end if c end if c 40 continue c call dgemv ('T' , ncv , nconv, & one , workl(invsub), ldq , & workl(ihbds), 1 , zero , & workev , 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = dlapy2 (workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call dcopy (nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call dtrmm ('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PDNAUPD into DR and DI | c %------------------------------------------------------% c call dcopy (nconv, workl(ritzr), 1, dr, 1) call dcopy (nconv, workl(ritzi), 1, di, 1) call dcopy (nconv, workl(ritzr), 1, workl(iheigr), 1) call dcopy (nconv, workl(ritzi), 1, workl(iheigi), 1) call dcopy (nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) do 50 k=1, ncv temp = dlapy2 (workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = dlapy2 (workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1) / temp / temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1) / temp / temp & + sigmai 80 continue c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call pdvout (comm, logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call pdvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call pdvout (comm, logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call pdvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheigr+j-1) else if (iconj .eq. 0) then temp = dlapy2 ( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call dger (n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of PDNEUPD | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdngets.f000066400000000000000000000202721260666001200175310ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdngets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pdngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Double precision array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortc ARPACK sorting routine. c dcopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ngets.F SID: 2.2 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine pdngets & ( comm, ishift, which, kev, np, ritzr, ritzi, & bounds, shiftr, shifti ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dsortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call dsortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call dsortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call dsortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine pdnapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call dsortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pdvout (comm, logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call pdvout (comm, logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call pdvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pdngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdnorm2.f000066400000000000000000000035161260666001200174500ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnorm2 c c Message Passing Layer: BLACS c c\Description: c c\Usage: c call pdnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 2/22/96 c c----------------------------------------------------------------------- c Double precision function pdnorm2 ( comm, n, x, inc ) c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d, dgamx2d c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & x(n) c c %---------------% c | Local Scalars | c %---------------% c Double precision & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Double precision & dnrm2 External dnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pdnorm2 = dnrm2( n, x, inc) c max = pdnorm2 call dgamx2d( comm, 'All', ' ', 1, 1, max, 1, ra, ca, & -1, -1, -1 ) if ( max .eq. zero ) then pdnorm2 = zero else pdnorm2 = (pdnorm2/max)**2.0 call dgsum2d( comm, 'All', ' ', 1, 1, pdnorm2, 1, -1, -1 ) pdnorm2 = max * sqrt(abs(pdnorm2)) endif c c %----------------% c | End of pdnorm2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdsaitr.f000066400000000000000000000764051260666001200175440ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pdsaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pdsaitr c ( COMM, IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See pdsaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c pdgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c pdmout Parallel ARPACK utility routine that prints matrices. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saitr.F SID: 2.3 c c\SCCS Information: c FILE: saitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pdsaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaitr & (comm, ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, infol, & jj Double precision & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, pdgetv0, pdvout, pdmout, & dlascl, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, pdlamch external ddot, pdnorm2, pdlamch c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = pdlamch(comm,'safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pdgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pdgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c wnorm = ddot (n, resid, 1, workd(ivj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then wnorm = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call dgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workl(1), 1) call dgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) else if (mode .eq. 2) then call dgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workl(1), 1) call dgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv('N', n, j, -one, v, ldv, workl(1), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workl(j) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call dgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workl(j) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = ddot (n, resid, 1, workd(ipj), 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm1, 1, -1, -1 ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = pdnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call dscal(n, -one, v(1,j+1), 1) else call dscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call pdvout (comm, logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call pdvout (comm, logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pdsaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdsapps.f000066400000000000000000000446501260666001200175450ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pdsapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Double precision array of length NP. (INPUT) c The shifts to be applied. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c dlartg LAPACK Givens rotation construction routine. c dlacpy LAPACK matrix copy routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sapps.F SID: 2.4 c c\SCCS Information: c FILE: sapps.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Double precision & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlartg, dlaset, pdvout, & pivout, arscnd, dgemv c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch external pdlamch c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = pdlamch(comm, 'Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call pdvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call dscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pdvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call daxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call pdvout (comm, logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call pdvout (comm, logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call pdvout (comm, logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdsapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdsaup2.f000066400000000000000000001010601260666001200174360ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by pdsaupd. c c\Usage: c call pdsaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pdsaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pdsaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the second column c of H starting at H(1,2). If pdsaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Double precision array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in pdsaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c pdgetv0 Parallel ARPACK initial vector generation routine. c pdsaitr Parallel ARPACK Lanczos factorization routine. c pdsapps Parallel ARPACK application of implicit shifts routine. c dsconv ARPACK convergence of Ritz values routine. c pdseigt Parallel ARPACK compute Ritz values and error bounds routine. c pdsgets Parallel ARPACK reorder Ritz values and error bounds routine. c dsortr ARPACK sorting routine. c sstrqb ARPACK routine that computes all eigenvalues and the c last component of the eigenvectors of a symmetric c tridiagonal matrix using the implicit QL or QR method. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saup2.F SID: 2.4 c c\SCCS Information: c FILE: saup2.F SID: 1.5 DATE OF SID: 05/20/98 c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d c c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Double precision & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, pdgetv0, pdsaitr, dscal, dsconv, & pdseigt, pdsgets, pdsapps, & dsortr, pdvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, pdlamch external ddot, pdnorm2, pdlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pdlamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0/3.0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %---------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %---------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pdgetv0 ( comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call pdsaitr (comm, ido, bmat, n, 0, nev0, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pdsaitr was unable to build an Lanczos factorization| c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call pivout (comm, logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call pdsaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pdsaitr was unable to build an Lanczos factorization| c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call pdseigt ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call dcopy(kplusp, ritz, 1, workl(kplusp+1), 1) call dcopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call pdsgets ( comm, ishift, which, nev, np, ritz, & bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(np+1), 1) call dsconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call pdvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call dsortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then call dswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call dswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call dsortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call dsortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call pdvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pdsgets ( comm, ishift, which, nev, np, & ritz, bounds, workl) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_saup2: NEV and NP .') call pdvout (comm, logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call pdvout (comm, logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, pdsgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call dcopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call pdvout (comm, logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call pdvout (comm, logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After pdsapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call pdsapps ( comm, n, nev, np, ritz, v, ldv, h, ldh, resid, & q, ldq, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pdsaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) call dgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call pdvout (comm, logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call pdvout (comm, logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %----------------% c | End of pdsaup2 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdsaupd.f000066400000000000000000000717641260666001200175410ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaupd c c Message Passing Layer: BLACS c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pdsaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pdsaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdsaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pdsaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Double precision N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of pdsaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pdsaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by pdseupd . See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c pdseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine pdseupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine dsteqr . c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine pdseupd . c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call pdseupd immediately following completion c of pdsaupd . This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c pdsaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c dstats ARPACK routine that initializes timing and other statistics c variables. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c c\Authors c Kristi Maschhoff ( Parallel Code ) c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saupd.F SID: 2.4 c c\SCCS Information: c FILE: saupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pdsaup2 , pdvout , pivout, arscnd, dstats c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch external pdlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pdlamch (comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call pdsaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pdsaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call pdvout (comm, logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call pdvout (comm, logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.1' , 19x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if end if c 9000 continue c return c c %----------------% c | End of pdsaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdseigt.f000066400000000000000000000130731260666001200175250ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdseigt c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call pdseigt c ( COMM, RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Double precision N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Double precision array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Double precision work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from dstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seigt.F SID: 2.2 c c\SCCS Information: c FILE: seigt.F SID: 1.3 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdseigt & ( comm, rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dstqrb, pdvout, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call pdvout (comm, logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call pdvout (comm, logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c c call dcopy (n, h(1,2), 1, eig, 1) call dcopy (n-1, h(2,1), 1, workl, 1) call dstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %-----------------% c | End of pdseigt | c %-----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdseupd.f000066400000000000000000001036011260666001200175270ustar00rootroot00000000000000c\BeginDoc c c\Name: pdseupd c c Message Passing Layer: BLACS c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by PSSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in PSSAUPD documentation.) PSSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine PSSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call pdseupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as workspace. c c D Double precision array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by pdsaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by PSSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Double precision (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to PDNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSSEUPD following the last call c to PSSAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSSAUPD and the call to PSSEUPD. c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c PSSAUPD. They are not changed by PSSEUPD. c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointers into WORKL for addresses c of the above information computed by PSSEUPD. c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c PSSEUPD if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine dsteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: PSSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: DSEUPD got a different count of the number of converged c Ritz values than DSAUPD got. This indicates the user c probably made an error in passing data from DSAUPD to c DSEUPD or that the data was modified before entering c DSEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c dsesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c dsortr dsortr ARPACK sorting routine. c pdnorm2 Parallel ARPACK routine that computes the 2-norm of a vector. c pivout Parallel ARPACK utility routine that prints integers. c pdvout Parallel ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c pdlamch ScaLAPACK routine that determines machine constants. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dsteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c dger Level 2 BLAS rank one update to a matrix. c dcopy Level 1 BLAS that copies one vector to another . c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seupd.F SID: 2.4 c c\SCCS Information: c FILE: seupd.F SID: 1.11 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pdseupd & (comm , rvec , howmny, select, d , & z , ldz , sigma , bmat , n , & which , nev , tol , resid , ncv , & v , ldv , iparam, ipntr , workd, & workl , lworkl, info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Double precision & d(nev), resid(n), v(ldv,ncv), z(ldz, nev), & workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Double precision & bnorm2, rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2, dlacpy, dorm2r, dscal, & dsesrt, dsteqr, dswap , pdvout, pivout, dsortr c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdnorm2, pdlamch external pdnorm2, pdlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | pdsaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by pdsaupd and is not | c | modified by pdseupd. | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by pdseupd. | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | dsteqr. Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by dsteqr and by pdseupd. | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pdlamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of pdsaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = pdnorm2(comm, n, workd, 1) end if c if (msglvl .gt. 2) then call pdvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call pdvout(comm, logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irz). Move | c | the corresponding error estimates | c | in workl(bound) accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pdsgets(comm , ishift, which , & nev , np , workl(irz), & workl(bounds), workl) c if (msglvl .gt. 2) then call pdvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call pdvout(comm, logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ncv-1, workl(ih+1) , 1, workl(ihb), 1) call dcopy (ncv , workl(ih+ldh), 1, workl(ihd), 1) c call dsteqr('Identity', ncv , workl(ihd), & workl(ihb), workl(iq), ldq , & workl(iw) , ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call dcopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call pdvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call pdvout (comm, logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if (.not.select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call dcopy(ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call dcopy(ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call dcopy(ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c 30 end if c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call dcopy(nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call dcopy(nconv, workl(ritz), 1, d, 1) call dcopy(ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call dsesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy(ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by pdsaupd. | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call dcopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call dcopy (nconv, workl(ihd), 1, d, 1) call dsortr('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call dsesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy(ncv, workl(bounds), 1, workl(ihb), 1) call dscal(ncv, bnorm2/rnorm, workl(ihb), 1) call dsortr('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call dgeqr2(ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call dorm2r('Right' , 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr ) call dlacpy('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call dorm2r('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr ) c else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by pdsaupd. | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call dscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / ( workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call pdvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call pdvout (comm, logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call pdvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / (workl(iw+k)-one) 120 continue c end if c if (type .ne. 'REGULR') & call dger(n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %----------------% c | End of pdseupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdsgets.f000066400000000000000000000171641260666001200175440ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsgets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pdsgets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Double precision array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Double precision array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortr ARPACK utility sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c dswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sgets.F SID: 2.3 c c\SCCS Information: c FILE: sgets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsgets & ( comm, ishift, which, kev, np, ritz, bounds, shifts ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dswap, dcopy, dsortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call dsortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call dswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call dswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call dsortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pdsapps. | c %-------------------------------------------------------% c call dsortr ('SM', .true., np, bounds, ritz) call dcopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_sgets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_sgets: NP is') call pdvout (comm, logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call pdvout (comm, logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %----------------% c | End of pdsgets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pdznorm2.f000066400000000000000000000035301260666001200176360ustar00rootroot00000000000000c\BeginDoc c c\Name: pdznorm2 c c Message Passing Layer: BLACS c c\Description: c c\Usage: c call pdznorm2 ( COMM, N, X, INC ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 3/6/96 c c----------------------------------------------------------------------- c Double precision function pdznorm2 ( comm, n, x, inc ) c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external dgsum2d, dgamx2d c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & x(n) c c %---------------% c | Local Scalars | c %---------------% c Double precision & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2 External dznrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pdznorm2 = dznrm2( n, x, inc) c max = pdznorm2 call dgamx2d( comm, 'All', ' ', 1, 1, max, 1, ra, ca, & -1, -1, -1 ) if ( max .eq. zero ) then pdznorm2 = zero else pdznorm2 = (pdznorm2/max)**2.0 call dgsum2d( comm, 'All', ' ', 1, 1, pdznorm2, 1, -1, -1 ) pdznorm2 = max * sqrt(abs(pdznorm2)) endif c c %-----------------% c | End of pdznorm2 | c %-----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pscnorm2.f000066400000000000000000000034611260666001200176310ustar00rootroot00000000000000c\BeginDoc c c\Name: pscnorm2 c c Message Passing Layer: BLACS c c\Description: c c\Usage: c call pscnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 3/6/96 c c----------------------------------------------------------------------- c Real function pscnorm2 ( comm, n, x, inc ) c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d, sgamx2d c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Complex & x(n) c c %---------------% c | Local Scalars | c %---------------% c Real & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2 External scnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pscnorm2 = scnrm2( n, x, inc) c max = pscnorm2 call sgamx2d( comm, 'All', ' ', 1, 1, max, 1, ra, ca, & -1, -1, -1 ) if ( max .eq. zero ) then pscnorm2 = zero else pscnorm2 = (pscnorm2/max)**2.0 call sgsum2d( comm, 'All', ' ', 1, 1, pscnorm2, 1, -1, -1 ) pscnorm2 = max * sqrt(abs(pscnorm2)) endif c c %-----------------% c | End of pscnorm2 | c %-----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psgetv0.f000066400000000000000000000331011260666001200174500ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psgetv0 c c Message Passing Layer: BLACS c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call psgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to psgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that psgetv0 is called. c It should be set to 1 on the initial call to psgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Real N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Real work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Real work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine for vector output. c pslarnv Parallel wrapper for LAPACK routine slarnv (generates a random vector). c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: getv0.F SID: 2.3 c c\SCCS Information: c FILE: getv0.F SID: 1.4 DATE OF SID: 3/19/97 c c\EndLib c c----------------------------------------------------------------------- c subroutine psgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Real & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external pslarnv, psvout, scopy, sgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2 external sdot, psnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pslarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call scopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c first = .FALSE. if (bmat .eq. 'G') then rnorm0 = sdot (n, resid, 1, workd, 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm0, 1, -1, -1 ) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = psnorm2( comm, n, resid, 1 ) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call sgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workl, 1) call sgsum2d( comm, 'All', ' ', j-1, 1, workl, j, -1, -1 ) call sgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call psvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of psgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pslamch.f000066400000000000000000000050761260666001200175210ustar00rootroot00000000000000 REAL FUNCTION PSLAMCH( ICTXT, CMACH ) * * -- ScaLAPACK auxilliary routine (version 1.0) -- * University of Tennessee, Knoxville, Oak Ridge National Laboratory, * and University of California, Berkeley. * February 28, 1995 * * .. Scalar Arguments .. CHARACTER CMACH INTEGER ICTXT * .. * * Purpose * ======= * * PSLAMCH determines single precision machine parameters. * * Arguments * ========= * * ICTXT (global input) INTEGER * The BLACS context handle in which the computation takes * place. * * CMACH (global input) CHARACTER*1 * Specifies the value to be returned by PSLAMCH: * = 'E' or 'e', PSLAMCH := eps * = 'S' or 's , PSLAMCH := sfmin * = 'B' or 'b', PSLAMCH := base * = 'P' or 'p', PSLAMCH := eps*base * = 'N' or 'n', PSLAMCH := t * = 'R' or 'r', PSLAMCH := rnd * = 'M' or 'm', PSLAMCH := emin * = 'U' or 'u', PSLAMCH := rmin * = 'L' or 'l', PSLAMCH := emax * = 'O' or 'o', PSLAMCH := rmax * * where * * eps = relative machine precision * sfmin = safe minimum, such that 1/sfmin does not overflow * base = base of the machine * prec = eps*base * t = number of (base) digits in the mantissa * rnd = 1.0 when rounding occurs in addition, 0.0 otherwise * emin = minimum exponent before (gradual) underflow * rmin = underflow threshold - base**(emin-1) * emax = largest exponent before overflow * rmax = overflow threshold - (base**emax)*(1-eps) * * ===================================================================== * * .. Local Scalars .. INTEGER IDUMM REAL TEMP * .. * .. External Subroutines .. EXTERNAL SGAMN2D, SGAMX2D * .. * .. External Functions .. LOGICAL LSAME REAL SLAMCH EXTERNAL LSAME, SLAMCH * .. * .. Executable Statements .. * TEMP = SLAMCH( CMACH ) * IF( LSAME( CMACH, 'E' ).OR.LSAME( CMACH, 'S' ).OR. $ LSAME( CMACH, 'M' ).OR.LSAME( CMACH, 'U' ) ) THEN CALL SGAMX2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, $ IDUMM, 1, -1, IDUMM ) ELSE IF( LSAME( CMACH, 'L' ).OR.LSAME( CMACH, 'O' ) ) THEN CALL SGAMN2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, $ IDUMM, 1, -1, IDUMM ) END IF * PSLAMCH = TEMP * * End of PSLAMCH * END arpack-ng-3.3.0/PARPACK/SRC/BLACS/pslarnv.f000066400000000000000000000037501260666001200175540ustar00rootroot00000000000000c\BeginDoc c c\Name: pslarnv c c Message Passing Layer: BLACS c c\Description: c c Parallel Version of ARPACK utility routine slarnv c c PSLARNV returns a vector of n (nloc) random real numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM BLACS Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Real array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine slarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine SLARNV to generate random c real numbers from a uniform (0,1) distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.4 DATE OF SID: 04/16/99 c c----------------------------------------------------------------------- c subroutine pslarnv( comm, idist, iseed, n, x ) c c .. BLACS VARIABLES AND FUNCTIONS .. integer comm c c .. External Functions .. external BLACS_GRIDINFO c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Real & x( * ) c .. c .. External Subroutines .. external slarnv c .. c .. Executable Statements .. c call slarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psnaitr.f000066400000000000000000000753741260666001200175620ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psnaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in psnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call psnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See psnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Real work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c psgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psmout Parallel ARPACK utility routine that prints matrices c psvout Parallel ARPACK utility routine that prints vectors. c slabad LAPACK routine that computes machine constants. c pslamch ScaLAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c slanhs LAPACK routine that computes various norms of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naitr.F SID: 2.2 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in psnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, psgetv0, slabad, & psvout, psmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, slanhs, pslamch external sdot, psnorm2, slanhs, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------% c unfl = pslamch(comm, 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | psgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call psvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call psgetv0 ( comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then wnorm = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) call sgsum2d( comm, 'All', ' ', j, 1, h(1,j), j, -1, -1 ) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call psvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call sgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call saxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm1, 1, -1, -1 ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = psnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call psmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of psnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psnapps.f000066400000000000000000000560301260666001200175520ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psnapps c c Message Passing Layer: BLACS c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call psnapps c ( COMM, N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Real array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to psnapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c slabad LAPACK routine that computes machine constants. c slacpy LAPACK matrix copy routine. c pslamch ScaLAPACK routine that determines machine constants. c slanhs LAPACK routine that computes various norms of a matrix. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slarf LAPACK routine that applies Householder reflection to c a matrix. c slarfg LAPACK Householder reflection construction routine. c slartg LAPACK Givens rotation construction routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another . c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: napps.F SID: 2.2 c c\SCCS Information: c FILE: napps.F SID: 1.5 DATE OF SID: 03/19/97 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine slahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine psnapps & ( comm, n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, & q, ldq, workl, workd ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Real & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slarf, slarfg, slartg, & slaset, slabad, arscnd, pivout, psvout, psmout c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch, slanhs, slapy2 external pslamch, slanhs, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------------% c unfl = pslamch( comm, 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call psvout (comm, logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call psvout (comm, logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call psvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call slartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = slapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call slarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call slarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call slarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call slarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call sscal( kplusp-j+1, -one, h(j+1,j), ldh ) call sscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call sscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call sgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %---------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %---------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call saxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call psvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call psmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %----------------% c | End of psnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psnaup2.f000066400000000000000000000765721260666001200174730ustar00rootroot00000000000000c\BeginDoc c c\Name: psnaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by psnaupd. c c\Usage: c call psnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in psnaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in psnaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from sneigh. c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c psgetv0 Parallel ARPACK initial vector generation routine. c psnaitr Parallel ARPACK Arnoldi factorization routine. c psnapps Parallel ARPACK application of implicit shifts routine. c snconv ARPACK convergence of Ritz values routine. c psneigh Parallel ARPACK compute Ritz values and error bounds routine. c psngets Parallel ARPACK reorder Ritz values and error bounds routine. c ssortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psmout Parallel ARPACK utility routine that prints matrices c psvout ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Revision history: c Starting Point: Serial Code FILE: naup2.F SID: 2.2 c c\SCCS Information: c FILE: naup2.F SID: 1.5 DATE OF SID: 06/01/00 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Real & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv, & j Real & rnorm , temp , eps23 save cnorm , getv0, initv , update, ushift, & rnorm , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , eps23 , numcnv c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, psgetv0, psnaitr, snconv, & psneigh, psngets, psnapps, & psvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, slapy2, pslamch external sdot, psnorm2, slapy2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call psgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call psnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine psnapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call psnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call psneigh ( comm, rnorm, kplusp, h, ldh, ritzr, ritzi, & bounds, q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from psneigh. | c %----------------------------------------------------% c call scopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1) call scopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of psngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call psngets ( comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call snconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call pivout (comm, logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call psvout (comm, logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call psvout (comm, logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call svout(logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with sngets, we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in sngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call ssortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call ssortc(wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call ssortc(wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call ssortc(which, .true., nconv, ritzr, ritzi, bounds) c c if (msglvl .gt. 1) then call svout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call svout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call svout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call psngets(comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call psvout (comm, logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call psvout (comm, logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call psvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call scopy (np, workl, 1, ritzr, 1) call scopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call psvout (comm, logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call psvout (comm, logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call psvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call psnapps (comm, n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to psnaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if cnorm = .false. c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call psmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of psnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psnaupd.f000066400000000000000000000731701260666001200175440ustar00rootroot00000000000000c\BeginDoc c c\Name: psnaupd c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine ssaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c psnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call psnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to psnaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c psnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Real array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of psnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), psnaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by sneupd. See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c psneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine sneupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine sneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call sneupd immediately following c completion of psnaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Real resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Real resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c psnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.9 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external psnaup2, psvout, pivout, arscnd, sstatn c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pslamch(comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine psneigh called | c | by psnaup2. Subroutine sneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call psnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within psnaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call psvout (comm, logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call psvout (comm, logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call psvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of psnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psneigh.f000066400000000000000000000247521260666001200175310ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psneigh c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call psneigh c ( COMM, RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Real N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Real N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from slahqr or strevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c slahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c slacpy LAPACK matrix copy routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another . c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neigh.F SID: 2.2 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine psneigh ( comm, rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Real & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, slacpy, slahqr, strevc, svout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2 external slapy2, snrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call psmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | slahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call slacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = one call slahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call psvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call strevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = snrm2( n, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2( snrm2( n, q(1,i), 1 ), & snrm2( n, q(1,i+1), 1 ) ) call sscal ( n, one / temp, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call sgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * slapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call psvout (comm, logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call psvout (comm, logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call psvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of psneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psneupd.f000066400000000000000000001264111260666001200175450ustar00rootroot00000000000000c\BeginDoc c c\Name: psneupd c c Message Passing Layer: BLACS c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PSNAUPD. PSNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine PSNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of PSNAUPD. c c\Usage: c call psneupd c ( COMM, RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Real array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c PSNAUPD. A further computation must be performed by the user c to transform the Ritz values computed for OP by PSNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Real array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Real N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PSNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Real (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Real (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Real work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PSNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSNEUPD following the last call c to PSNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSNAUPD and the call to PSNEUPD. c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Real N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PSNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c PSNAUPD. They are not changed by PSNEUPD. c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointers into WORKL for addresses c of the above information computed by PSNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PSNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine slahqr c could not be reordered by LAPACK routine strsen. c Re-enter subroutine psneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine slahqr. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine strevc. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PSNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: PSNEUPD got a different count of the number of converged c Ritz values than PSNAUPD got. This indicates the user c probably made an error in passing data from PSNAUPD to c PSNEUPD or that the data was modified before entering c PSNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c psmout Parallel ARPACK utility routine that prints matrices c psvout Parallel ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c slahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK matrix initialization routine. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c strsen LAPACK routine that re-orders the Schur form. c strmm Level 3 BLAS matrix times an upper triangular matrix. c sger Level 2 BLAS rank one update to a matrix. c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X` denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by PSNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c Z(:,I)` * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c Z(:,I)` * A * Z(:,I) + Z(:,I+1)` * A * Z(:,I+1), c Z(:,I)` * A * Z(:,I+1) - Z(:,I+1)` * A * Z(:,I), respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute V(:,1:IPARAM(5))` * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neupd.F SID: 2.3 c c\SCCS Information: c FILE: neupd.F SID: 1.8 DATE OF SID: 04/10/01 c c\EndLib c c----------------------------------------------------------------------- subroutine psneupd & (comm , rvec , howmny, select, dr , di , & z , ldz , sigmar, sigmai, workev, bmat, & n , which, nev , tol , resid , & ncv , v , ldv , iparam, ipntr , & workd, workl, lworkl, info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & dr(nev+1) , di(nev+1) , resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr, ih, ihbds, & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj logical reord Real & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, & slahqr, slaset, psmout, sorm2r, & strevc, strmm , strsen, sscal , & psvout, pivout c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2, pslamch external slapy2, snrm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by PSNEUPD. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call psvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call psvout (comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call psngets(comm , ishift , which , & nev , np , workl(irr), & workl(iri), workl(bounds), & workl , workl(np+1)) c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call psvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call psvout (comm, logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & slapy2 ( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine slahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by PSNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call slaset('All', ncv, ncv, zero, one, workl(invsub), ldq) call slahqr(.true. , .true. , ncv, 1 , & ncv , workl(iuptri), ldh, workl(iheigr), & workl(iheigi), 1 , ncv, workl(invsub), & ldq , ierr) call scopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call psvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call psvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call psvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call psmout (comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call strsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheigr), & workl(iheigi), nconv , conds , & sep , workl(ihbds) , ncv , & iwork , 1 , ierr ) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call psvout(comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call psmout(comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call scopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using sorm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call slacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call sscal(nconv, -one, workl(iuptri+j-1), ldq) call sscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call strevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = snrm2( ncv, workl(invsub+(j-1)*ldq), 1 ) call sscal ( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2(snrm2(ncv, & workl(invsub+(j-1)*ldq), & 1 ), & snrm2(ncv, & workl(invsub+j*ldq), & 1) & ) call sscal(ncv, one/temp, & workl(invsub+(j-1)*ldq), 1) call sscal(ncv, one/temp, & workl(invsub+j*ldq), 1) iconj = 1 else iconj = 0 end if c end if c 40 continue c call sgemv('T' , ncv , nconv, & one , workl(invsub), ldq , & workl(ihbds), 1 , zero , & workev , 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = slapy2(workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call psmout(comm, logfil, ncv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call scopy(nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call strmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PSNAUPD into DR and DI | c %------------------------------------------------------% c call scopy(nconv, workl(ritzr), 1, dr, 1) call scopy(nconv, workl(ritzi), 1, di, 1) call scopy(nconv, workl(ritzr), 1, workl(iheigr), 1) call scopy(nconv, workl(ritzi), 1, workl(iheigi), 1) call scopy(nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) do 50 k=1, ncv temp = slapy2(workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = slapy2(workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1) / temp / temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1) / temp / temp & + sigmai 80 continue c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call psvout (comm, logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call psvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call psvout (comm, logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call psvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheigr+j-1) else if (iconj .eq. 0) then temp = slapy2( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call sger(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of PSNEUPD | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psngets.f000066400000000000000000000202121260666001200175420ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psngets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call psngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Real array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortc ARPACK sorting routine. c scopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ngets.F SID: 2.2 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine psngets & ( comm, ishift, which, kev, np, ritzr, ritzi, & bounds, shiftr, shifti ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, ssortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call ssortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call ssortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call ssortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine psnapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call ssortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call psvout (comm, logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call psvout (comm, logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call psvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of psngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psnorm2.f000066400000000000000000000034361260666001200174700ustar00rootroot00000000000000c\BeginDoc c c\Name: psnorm2 c c Message Passing Layer: BLACS c c\Description: c c\Usage: c call psnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 2/22/96 c c----------------------------------------------------------------------- c Real function psnorm2 ( comm, n, x, inc ) c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d, sgamx2d c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Real & x(n) c c %---------------% c | Local Scalars | c %---------------% c Real & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Real & snrm2 External snrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c psnorm2 = snrm2( n, x, inc) c max = psnorm2 call sgamx2d( comm, 'All', ' ', 1, 1, max, 1, ra, ca, & -1, -1, -1 ) if ( max .eq. zero ) then psnorm2 = zero else psnorm2 = (psnorm2/max)**2.0 call sgsum2d( comm, 'All', ' ', 1, 1, psnorm2, 1, -1, -1 ) psnorm2 = max * sqrt(abs(psnorm2)) endif c c %----------------% c | End of psnorm2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pssaitr.f000066400000000000000000000761651260666001200175660ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pssaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pssaitr c ( COMM, IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See pssaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c WORKL Real work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c psgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c psmout Parallel ARPACK utility routine that prints matrices. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saitr.F SID: 2.3 c c\SCCS Information: c FILE: saitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pssaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaitr & (comm, ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, infol, & jj Real & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, psgetv0, psvout, psmout, & slascl, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, pslamch external sdot, psnorm2, pslamch c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = pslamch(comm,'safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | psgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call psvout (comm, logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call psgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c wnorm = sdot (n, resid, 1, workd(ivj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then wnorm = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, wnorm, 1, -1, -1 ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call sgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workl(1), 1) call sgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) else if (mode .eq. 2) then call sgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workl(1), 1) call sgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv('N', n, j, -one, v, ldv, workl(1), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workl(j) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call sgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workl(j) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = sdot (n, resid, 1, workd(ipj), 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm1, 1, -1, -1 ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = psnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call sscal(n, -one, v(1,j+1), 1) else call sscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call psvout (comm, logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call psvout (comm, logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pssaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pssapps.f000066400000000000000000000444601260666001200175630ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pssapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Real array of length NP. (INPUT) c The shifts to be applied. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slartg LAPACK Givens rotation construction routine. c slacpy LAPACK matrix copy routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sapps.F SID: 2.4 c c\SCCS Information: c FILE: sapps.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine pssapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Real & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slartg, slaset, psvout, & pivout, arscnd, sgemv c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = pslamch(comm, 'Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call psvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call sscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call psvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call sgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call saxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call psvout (comm, logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call psvout (comm, logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call psvout (comm, logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %----------------% c | End of pssapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pssaup2.f000066400000000000000000001006401260666001200174600ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by pssaupd. c c\Usage: c call pssaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pssaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pssaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the second column c of H starting at H(1,2). If pssaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Real array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in pssaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c psgetv0 Parallel ARPACK initial vector generation routine. c pssaitr Parallel ARPACK Lanczos factorization routine. c pssapps Parallel ARPACK application of implicit shifts routine. c ssconv ARPACK convergence of Ritz values routine. c psseigt Parallel ARPACK compute Ritz values and error bounds routine. c pssgets Parallel ARPACK reorder Ritz values and error bounds routine. c ssortr ARPACK sorting routine. c sstrqb ARPACK routine that computes all eigenvalues and the c last component of the eigenvectors of a symmetric c tridiagonal matrix using the implicit QL or QR method. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saup2.F SID: 2.4 c c\SCCS Information: c FILE: saup2.F SID: 1.5 DATE OF SID: 05/20/98 c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external sgsum2d c c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Real & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, psgetv0, pssaitr, sscal, ssconv, & psseigt, pssgets, pssapps, & ssortr, psvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, pslamch external sdot, psnorm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0/3.0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %---------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %---------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call psgetv0 ( comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call pssaitr (comm, ido, bmat, n, 0, nev0, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pssaitr was unable to build an Lanczos factorization| c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call pivout (comm, logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call pssaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pssaitr was unable to build an Lanczos factorization| c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call psseigt ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call scopy(kplusp, ritz, 1, workl(kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call pssgets ( comm, ishift, which, nev, np, ritz, & bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(np+1), 1) call ssconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call psvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call ssortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then call sswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call sswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call ssortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call ssortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call psvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pssgets ( comm, ishift, which, nev, np, & ritz, bounds, workl) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_saup2: NEV and NP .') call psvout (comm, logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call psvout (comm, logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, pssgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call scopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call psvout (comm, logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call psvout (comm, logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After pssapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call pssapps ( comm, n, nev, np, ritz, v, ldv, h, ldh, resid, & q, ldq, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pssaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) call sgsum2d( comm, 'All', ' ', 1, 1, rnorm, 1, -1, -1 ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call psvout (comm, logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call psvout (comm, logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %----------------% c | End of pssaup2 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pssaupd.f000066400000000000000000000715471260666001200175570ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaupd c c Message Passing Layer: BLACS c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pssaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pssaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pssaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pssaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Real N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of pssaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pssaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by psseupd. See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c psseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine psseupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine psseupd. c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call psseupd immediately following completion c of pssaupd. This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c pssaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c sstats ARPACK routine that initializes timing and other statistics c variables. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c c\Authors c Kristi Maschhoff ( Parallel Code ) c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saupd.F SID: 2.4 c c\SCCS Information: c FILE: saupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pssaup2, psvout, pivout, arscnd, sstats c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pslamch(comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call pssaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pssaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call psvout (comm, logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call psvout (comm, logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.1' , 19x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if end if c 9000 continue c return c c %----------------% c | End of pssaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psseigt.f000066400000000000000000000127331260666001200175460ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psseigt c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call psseigt c ( COMM, RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Real N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Real array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Real work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from sstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c sstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seigt.F SID: 2.2 c c\SCCS Information: c FILE: seigt.F SID: 1.3 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine psseigt & ( comm, rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, sstqrb, psvout, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call psvout (comm, logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call psvout (comm, logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c c call scopy (n, h(1,2), 1, eig, 1) call scopy (n-1, h(2,1), 1, workl, 1) call sstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call psvout (comm, logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %-----------------% c | End of psseigt | c %-----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/psseupd.f000066400000000000000000001034251260666001200175520ustar00rootroot00000000000000c\BeginDoc c c\Name: psseupd c c Message Passing Layer: BLACS c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by PSSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in PSSAUPD documentation.) PSSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine PSSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call psseupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as workspace. c c D Real array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by pssaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by PSSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Real (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to PSNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSSEUPD following the last call c to PSSAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSSAUPD and the call to PSSEUPD. c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c PSSAUPD. They are not changed by PSSEUPD. c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointers into WORKL for addresses c of the above information computed by PSSEUPD. c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c PSSEUPD if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: PSSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: SSEUPD got a different count of the number of converged c Ritz values than SSAUPD got. This indicates the user c probably made an error in passing data from SSAUPD to c SSEUPD or that the data was modified before entering c SSEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c ssesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c ssortr ssortr ARPACK sorting routine. c psnorm2 Parallel ARPACK routine that computes the 2-norm of a vector. c pivout Parallel ARPACK utility routine that prints integers. c psvout Parallel ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c pslamch ScaLAPACK routine that determines machine constants. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c ssteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c sger Level 2 BLAS rank one update to a matrix. c scopy Level 1 BLAS that copies one vector to another . c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seupd.F SID: 2.4 c c\SCCS Information: c FILE: seupd.F SID: 1.11 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine psseupd & (comm , rvec , howmny, select, d , & z , ldz , sigma , bmat , n , & which , nev , tol , resid , ncv , & v , ldv , iparam, ipntr , workd, & workl , lworkl, info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Real & d(nev), resid(n), v(ldv,ncv), z(ldz, nev), & workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Real & bnorm2, rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, sorm2r, sscal, & ssesrt, ssteqr, sswap , psvout, pivout, ssortr c c %--------------------% c | External Functions | c %--------------------% c Real & psnorm2, pslamch external psnorm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | pssaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by pssaupd and is not | c | modified by psseupd. | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by psseupd. | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | ssteqr. Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by ssteqr and by psseupd. | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of pssaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = psnorm2(comm, n, workd, 1) end if c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call psvout(comm, logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irz). Move | c | the corresponding error estimates | c | in workl(bound) accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pssgets(comm , ishift, which , & nev , np , workl(irz), & workl(bounds), workl) c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call psvout(comm, logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy (ncv-1, workl(ih+1) , 1, workl(ihb), 1) call scopy (ncv , workl(ih+ldh), 1, workl(ihd), 1) c call ssteqr('Identity', ncv , workl(ihd), & workl(ihb), workl(iq), ldq , & workl(iw) , ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call scopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call psvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call psvout (comm, logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if (.not.select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call scopy(ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call scopy(ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call scopy(ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c 30 end if c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call scopy(nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call scopy(nconv, workl(ritz), 1, d, 1) call scopy(ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by pssaupd. | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call scopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call scopy (nconv, workl(ihd), 1, d, 1) call ssortr('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) call sscal(ncv, bnorm2/rnorm, workl(ihb), 1) call ssortr('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call sorm2r('Right' , 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr ) call slacpy('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call sorm2r('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr ) c else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by pssaupd. | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call sscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / ( workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call psvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call psvout (comm, logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call psvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / (workl(iw+k)-one) 120 continue c end if c if (type .ne. 'REGULR') & call sger(n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %----------------% c | End of psseupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pssgets.f000066400000000000000000000170701260666001200175570ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssgets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pssgets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Real array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Real array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortr ARPACK utility sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c sswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sgets.F SID: 2.3 c c\SCCS Information: c FILE: sgets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pssgets & ( comm, ishift, which, kev, np, ritz, bounds, shifts ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external sswap, scopy, ssortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call ssortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call sswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call sswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call ssortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pssapps. | c %-------------------------------------------------------% c call ssortr ('SM', .true., np, bounds, ritz) call scopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_sgets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_sgets: NP is') call psvout (comm, logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call psvout (comm, logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %----------------% c | End of pssgets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pzgetv0.f000066400000000000000000000347471260666001200175000ustar00rootroot00000000000000c\BeginDoc c c\Name: pzgetv0 c c Message Passing Layer: BLACS c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pzgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pzgetv0 . c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pzgetv0 is called. c It should be set to 1 on the initial call to pzgetv0 . c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex*16 N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex*16 work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Complex*16 work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c pzvout Parallel ARPACK utility routine that prints vectors. c pzlarnv Parallel wrapper for LAPACK routine zlarnv (generates a random vector). c zgemv Level 2 BLAS routine for matrix vector multiplication. c zcopy Level 1 BLAS that copies one vector to another. c zdotc Level 1 BLAS that computes the scalar product of two vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: getv0.F SID: 2.1 c c\SCCS Information: c FILE: getv0.F SID: 1.7 DATE OF SID: 04/12/01 c c\EndLib c c----------------------------------------------------------------------- c subroutine pzgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm, nprow, npcol, myprow, mypcol external zgsum2d , blacs_gridinfo c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) , & rzero = 0.0 ) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj, myid, igen Double precision & rnorm0 Complex*16 & cnorm, cnorm2 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy , zgemv , pzlarnv , pzvout , arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdznorm2 , dlapy2 Complex*16 & zdotc external zdotc , pdznorm2 , dlapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then c c %-----------------------------------% c | Generate a seed on each processor | c | using process id (myid). | c | Note: the seed must be between 1 | c | and 4095. iseed(4) must be odd. | c %-----------------------------------% c call BLACS_GRIDINFO(comm, nprow, npcol, myprow, mypcol) c c %-------------------------------------------% c | Convert a 2-D process id (myprow, mypcol) | c | to a 1-D process id (myid). | c %-------------------------------------------% c myid = npcol*myprow + mypcol + 1 igen = 1000 + 2*myid - 1 if (igen .gt. 4095) then write(0,*) 'Error in p_getv0: seed exceeds 4095!' end if c iseed(1) = igen/1000 igen = mod(igen,1000) iseed(2) = igen/100 igen = mod(igen,100) iseed(3) = igen/10 iseed(4) = mod(igen,10) c inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pzlarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call zcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd, 1) call zgsum2d ( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm0 = sqrt(dlapy2 (dble (cnorm),dimag (cnorm))) else if (bmat .eq. 'I') then rnorm0 = pdznorm2 ( comm, n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett`s book, page 107 and in Gragg and Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call zgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workl, 1) call zgsum2d ( comm, 'All', ' ', j-1, 1, workl, j, -1, -1 ) call zgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd, 1) call zgsum2d ( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm = sqrt(dlapy2 (dble (cnorm),dimag (cnorm))) else if (bmat .eq. 'I') then rnorm = pdznorm2 (comm, n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5 ) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then cnorm2 = dcmplx (rnorm,rzero) call pzvout (comm, logfil, 1, cnorm2, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pzvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pzgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pzlarnv.f000066400000000000000000000036401260666001200175610ustar00rootroot00000000000000c\BeginDoc c c\Name: pzlarnv c c Message Passing Layer: BLACS c c\Description: c c Parallel Version of ARPACK utility routine zlarnv c c PZLARNV returns a vector of n (nloc) random Complex*16 numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM BLACS Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Complex*16 array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine zlarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine CLARNV to generate random c Complex*16 numbers from a uniform or normal distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.3 DATE OF SID: 04/17/99 c c----------------------------------------------------------------------- c subroutine pzlarnv( comm, idist, iseed, n, x ) c integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Complex*16 & x( * ) c .. c .. External Subroutines .. external zlarnv c .. c .. Executable Statements .. c call zlarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pznaitr.f000066400000000000000000000766541260666001200175730ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaitr c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pznaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pznaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pznaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex*16 N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Complex*16 work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pzgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zlanhs LAPACK routine that computes various norms of a matrix. c zlascl LAPACK routine for careful scaling of a matrix. c dlabad LAPACK routine for defining the underflow and overflow c limits c pdlamch ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of c two vectors. c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c pdznorm2 Parallel version of Level 1 BLAS that computes the c norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: naitr.F SID: 2.1 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pznaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external zgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone, rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0, rzero = 0.0) c c %--------------% c | Local Arrays | c %--------------% c Double precision & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex*16 & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zscal, zgemv, pzgetv0, dlabad, & zdscal, pzvout, pzmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex*16 & zdotc Double precision & pdlamch, pdznorm2, zlanhs, dlapy2 external zdotc, pdznorm2, zlanhs, pdlamch, dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag, dble, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------% c unfl = pdlamch(comm, 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = pdlamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pzgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pzvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pzgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call zcopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call zdscal (n, temp1, v(1,j), 1) call zdscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine zlascl | c %-----------------------------------------% c call zlascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call zlascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call zcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call zcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) call zgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) wnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = pdznorm2(comm, n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) call zgsum2d( comm, 'All', ' ', j, 1, h(1,j), j, -1, -1 ) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = dcmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) call zgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = pdznorm2(comm, n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call pdvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call pzvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call zgsum2d( comm, 'All', ' ', j, 1, workl, j, -1, -1 ) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call zaxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) call zgsum2d( comm, 'All', ' ', 1, 1, cnorm, 1, -1, -1 ) rnorm1 = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = pdznorm2(comm, n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call pdvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %--------------------------------------------% c tst1 = dlapy2(dble(h(i,i)),dimag(h(i,i))) & + dlapy2(dble(h(i+1,i+1)), dimag(h(i+1,i+1))) if( tst1.eq.dble(zero) ) & tst1 = zlanhs( '1', k+np, h, ldh, workd(n+1) ) if( dlapy2(dble(h(i+1,i)),dimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pzmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pznaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pznapps.f000066400000000000000000000432371260666001200175660ustar00rootroot00000000000000c\BeginDoc c c\Name: pznapps c c Message Passing Layer: BLACS c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pznapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex*16 array of length NP. (INPUT) c The shifts to be applied. c c V Complex*16 N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex*16 KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex*16 work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlanhs LAPACK routine that computes various norms of a matrix. c zlartg LAPACK Givens rotation construction routine. c zlaset LAPACK matrix initialization routine. c dlabad LAPACK routine for defining the underflow and overflow c limits. c pdlamch ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another. c zscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: napps.F SID: 2.1 c c\SCCS Information: c FILE: napps.F SID: 1.4 DATE OF SID: 10/25/03 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine zlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine pznapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex*16 & cdum, f, g, h11, h21, r, s, sigma, t Double precision & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zgemv, zscal, zlacpy, zlartg, & pzvout, zlaset, dlabad, pzmout, arscnd, pivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & zlanhs, pdlamch, dlapy2 external zlanhs, pdlamch, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, dimag, conjg, dcmplx, max, min, dble c c %---------------------% c | Statement Functions | c %---------------------% c Double precision & cabs1 cabs1( cdum ) = abs( dble( cdum ) ) + abs( dimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------------% c unfl = pdlamch( comm, 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = dlamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call zlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pzvout (comm, logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %----------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = zlanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(dble(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pzvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call zlartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( dble( h(j+1,j) ) .lt. rzero .or. & dimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / dlapy2(dble(h(j+1,j)),dimag(h(j+1,j))) call zscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call zscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call zscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = dcmplx( dble( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = zlanhs( '1', kev, h, ldh, workl ) if( dble( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call zgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call zcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call zlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call zscal (n, q(kplusp,kev), resid, 1) if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zaxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pzvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pzvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pzmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %----------------% c | End of pznapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pznaup2.f000066400000000000000000000724161260666001200174730ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaup2 c c Message Passing Layer: BLACS c c\Description: c Intermediate level interface called by pznaupd. c c\Usage: c call pznaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pznaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pznaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex*16 N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex*16 array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex*16 (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in PZNAUPD. c c RWORK Double precision work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pzgetv0 Parallel ARPACK initial vector generation routine. c pznaitr Parallel ARPACK Arnoldi factorization routine. c pznapps Parallel ARPACK application of implicit shifts routine. c pzneigh Parallel ARPACK compute Ritz values and error bounds routine. c pzngets Parallel ARPACK reorder Ritz values and error bounds routine. c zsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c pdvout ARPACK utility routine that prints vectors. c pdlamch ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of two vectors. c zswap Level 1 BLAS that swaps two vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c FILE: naup2.F SID: 1.7 DATE OF SID: 10/25/03 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c c c %------------------------------% c | BLACS Variables and Routines | c %------------------------------% c integer comm external zgsum2d c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex*16 & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Double precision & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm, getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex*16 & cmpnorm Double precision & rnorm, eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0, eps23 c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy, pzgetv0, pznaitr, pzneigh, pzngets, pznapps, & zsortc, zswap, pzmout, pzvout, pivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex*16 & zdotc Double precision & pdznorm2, pdlamch, dlapy2 external zdotc, pdznorm2, pdlamch, dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag, dble, min, max, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pzgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pznaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pznapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pznaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pzneigh ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from pzneigh. | c %--------------------------------------------------% c call zcopy(kplusp,ritz,1,workl(kplusp**2+1),1) call zcopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call pzngets ( comm, ishift, which, nev, np, ritz, & bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, dlapy2( dble(ritz(np+i)), & dimag(ritz(np+i)) ) ) if ( dlapy2(dble(bounds(np+i)),dimag(bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call pzvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call pzvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call pzvout(comm, logfil, kplusp, & workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call pzvout(comm, logfil, kplusp, & workl(kplusp**2+kplusp+1), ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to pzneupd if needed | c %------------------------------------------% c h(3,1) = dcmplx(rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call zsortc(wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, dlapy2( dble(ritz(j)), & dimag(ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call zsortc(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, dlapy2( dble(ritz(j)), & dimag(ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call zsortc(which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call pzvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call pzvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pzngets (comm, ishift, which, nev, np, ritz, & bounds) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pzvout (comm, logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call pzvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call zcopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pzvout (comm, logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call pzvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pznapps(comm, n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pznaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm = zdotc (n, resid, 1, workd, 1) call zgsum2d( comm, 'All', ' ', 1, 1, cmpnorm, 1, -1, -1 ) rnorm = sqrt(dlapy2(dble(cmpnorm),dimag(cmpnorm))) else if (bmat .eq. 'I') then rnorm = pdznorm2(comm, n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pzmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pznaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pznaupd.f000066400000000000000000000676171260666001200175640ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaupd c c Message Passing Layer: BLACS c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then dsaupd or dnaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pznaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pznaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pznaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pznaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = pdlamch (comm, 'EPS') (machine precision as computed c by the ScaLAPACK auxiliary subroutine pdlamch ). c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below) c c V Complex*16 array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of pznaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by pzneupd . See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c zneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex*16 work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Double precision work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine pzneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call pzneupd immediately following c completion of pznaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex*16 resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex*16 resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pznaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c zstatn ARPACK routine that initializes the timing variables. c pivout Parallel ARPACK utility routine that prints integers. c pzvout Parallel ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c pdlamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, rwork, info ) c c c %-----------------------------------% c | BLACS processor info and Routines | c %-----------------------------------% c integer comm, nprow, npcol, myprow, mypcol external BLACS_GRIDINFO c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex*16 & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Double precision & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pznaup2 , pzvout , pivout, arscnd, zstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch external pdlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call zstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0 ) tol = pdlamch (comm, 'EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine pzneigh called | c | by pznaup2 . Subroutine pzneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pznaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pznaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pzvout (comm, logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call pzvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then call BLACS_GRIDINFO( comm, nprow, npcol, myprow, mypcol ) if ( (myprow .eq. 0) .and. (mypcol .eq. 0) ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pznaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pzneigh.f000066400000000000000000000207141260666001200175320ustar00rootroot00000000000000c\BeginDoc c c\Name: pzneigh c c Message Passing Layer: BLACS c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pzneigh c ( COMM, RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex*16 N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex*16 array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex*16 N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Double precision work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from zlahqr or ztrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c pdvout Parallel ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c zcopy Level 1 BLAS that copies one vector to another. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: neigh.F SID: 2.1 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pzneigh (comm, rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Double precision & rwork(n) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex*16 & vl(1) Double precision & temp c c %----------------------% c | External Subroutines | c %----------------------% c external zlacpy, zlahqr, zdscal, ztrevc, zcopy, & pzmout, pzvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2 external dznrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call pzmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | zlahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call zlacpy ('All', n, n, h, ldh, workl, n) call zlaset ('All', n, n, zero, one, q, ldq) call zlahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call zcopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call pzvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ztrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = dznrm2( n, q(1,j), 1 ) call zdscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call zcopy(n, q(n,1), ldq, workl, 1) call pzvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call zcopy(n, q(n,1), n, bounds, 1) call zdscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call pzvout (comm, logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call pzvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pzneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pzneupd.f000066400000000000000000001050061260666001200175510ustar00rootroot00000000000000c\BeginDoc c c\Name: pzneupd c c Message Passing Layer: BLACS c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PZNAUPD. PZNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of PZNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of PZNAUPD. c c\Usage: c call pzneupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex*16 array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex*16 N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PZNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex*16 (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex*16 work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PZNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to ZNEUPD following the last call c to PZNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PZNAUPD and the call to ZNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex*16 N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PZNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c PZNAUPD. They are not changed by PZNEUPD. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by PZNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PZNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ztrsen. c Re-enter subroutine pzneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ztrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PZNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: ZNEUPD got a different count of the number of converged c Ritz values than ZNAUPD got. This indicates the user c probably made an error in passing data from ZNAUPD to c ZNEUPD or that the data was modified before entering c ZNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ztrsen LAPACK routine that re-orders the Schur form. c zunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c pdlamch ScaLAPACK routine that determines machine constants. c ztrmm Level 3 BLAS matrix times an upper triangular matrix. c zgeru Level 2 BLAS rank one update to a matrix. c zcopy Level 1 BLAS that copies one vector to another . c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: neupd.F SID: 2.2 c c\SCCS Information: c FILE: neupd.F SID: 1.9 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pzneupd & ( comm , rvec , howmny, select, d , & z , ldz , sigma , workev, bmat , & n , which , nev , tol , resid, & ncv , v , ldv , iparam, ipntr, & workd, workl , lworkl, rwork , info ) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex*16 & sigma Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & rwork(ncv) Complex*16 & d(nev) , resid(n) , v(ldv,ncv) , & z(ldz, nev), workd(3*n), workl(lworkl), & workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift Complex*16 & rnorm, temp, vl(1) Double precision & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy ,zgeru,zgeqr2,zlacpy,pzmout, & zunm2r,ztrmm,pzvout,pivout, & zlahqr c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2,pdlamch,dlapy2 external dznrm2,pdlamch,dlapy2 c Complex*16 & zdotc external zdotc c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by ZNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pzvout(comm, logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call pzvout(comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pzngets(comm, ishift, which , & nev , np , workl(irz), & workl(bounds)) c if (msglvl .gt. 2) then call pzvout(comm,logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call pzvout(comm,logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & dlapy2 ( dble (workl(irz+ncv-j)), & dimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & dlapy2( dble (workl(ibd+jj-1)), & dimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine zlahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by PZNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call zcopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call zlaset('All', ncv, ncv, zero, one, workl(invsub), ldq) call zlahqr(.true. , .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr ) call zcopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pzvout(comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call pzvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pzmout(comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ztrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv , conds , sep , & workev, ncv, ierr) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pzvout (comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call pzmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call zcopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call zcopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call zgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using zunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call zunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call zlacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( dble( workl(invsub+(j-1)*ldq+j-1) ) .lt. & dble(zero) ) then call zscal(nconv, -one, workl(iuptri+j-1), ldq) call zscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ztrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr ) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = dznrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = dble(one) / rtemp call zdscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = zdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call zcopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call pzvout(comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pzmout(comm, logfil, nconv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call zcopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ztrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PZNAUPD into D. | c %--------------------------------------------------% c call zcopy(nconv, workl(ritz), 1, d, 1) call zcopy(nconv, workl(ritz), 1, workl(iheig), 1) call zcopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pzvout (comm, logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call pzvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call pzvout (comm, logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call pzvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call zgeru(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of pzneupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/pzngets.f000066400000000000000000000135131260666001200175570ustar00rootroot00000000000000c\BeginDoc c c\Name: pzngets c c Message Passing Layer: BLACS c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pzngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c COMM BLACS Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c zsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzvout Parallel ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: ngets.F SID: 2.1 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine pzngets ( comm, ishift, which, kev, np, ritz, bounds) c c %--------------------% c | BLACS Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external pzvout, zsortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call zsortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pznapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call zsortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pzvout (comm, logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call pzvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pzngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/BLACS/stat.h000066400000000000000000000017131260666001200170410ustar00rootroot00000000000000c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c c\SCCS Information: @(#) c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2 c real t0, t1, t2, t3, t4, t5 save t0, t1, t2, t3, t4, t5 c integer nopx, nbx, nrorth, nitref, nrstrt real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec common /timing/ & nopx, nbx, nrorth, nitref, nrstrt, & tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec arpack-ng-3.3.0/PARPACK/SRC/MPI/000077500000000000000000000000001260666001200155145ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/SRC/MPI/Makefile.am000066400000000000000000000017571260666001200175620ustar00rootroot00000000000000F77 = $(MPIF77) FFLAGS_SAV = @FFLAGS@ FFLAGS = SSRC = psnaitr.f psnapps.f psnaup2.f psnaupd.f psneigh.f psneupd.f psngets.f \ pssaitr.f pssapps.f pssaup2.f pssaupd.f psseigt.f psseupd.f pssgets.f \ psgetv0.f pslarnv.f psnorm2.f DSRC = pdnaitr.f pdnapps.f pdnaup2.f pdnaupd.f pdneigh.f pdneupd.f pdngets.f \ pdsaitr.f pdsapps.f pdsaup2.f pdsaupd.f pdseigt.f pdseupd.f pdsgets.f \ pdgetv0.f pdlarnv.f pdnorm2.f CSRC = pcnaitr.f pcnapps.f pcnaup2.f pcnaupd.f pcneigh.f pcneupd.f pcngets.f \ pcgetv0.f pclarnv.f pscnorm2.f ZSRC = pznaitr.f pznapps.f pznaup2.f pznaupd.f pzneigh.f pzneupd.f pzngets.f \ pzgetv0.f pzlarnv.f pdznorm2.f EXTRA_DIST = debug.h stat.h noinst_LTLIBRARIES = libparpack_noopt.la libparpacksrcmpi.la libparpack_noopt_la_SOURCES = pslamch.f pdlamch10.f libparpack_noopt_la_FFLAGS = -O0 libparpacksrcmpi_la_SOURCES = $(SSRC) $(DSRC) $(CSRC) $(ZSRC) libparpacksrcmpi_la_FFLAGS = $(FFLAGS_SAV) libparpacksrcmpi_la_LIBADD = libparpack_noopt.la arpack-ng-3.3.0/PARPACK/SRC/MPI/debug.h000066400000000000000000000013511260666001200167530ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/PARPACK/SRC/MPI/pcgetv0.f000066400000000000000000000342201260666001200172340ustar00rootroot00000000000000c\BeginDoc c c\Name: pcgetv0 c c Message Passing Layer: MPI c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pcgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pcgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pcgetv0 is called. c It should be set to 1 on the initial call to pcgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Complex work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c pcvout Parallel ARPACK utility routine that prints vectors. c pclarnv Parallel wrapper for LAPACK routine clarnv (generates a random vector). c cgemv Level 2 BLAS routine for matrix vector multiplication. c ccopy Level 1 BLAS that copies one vector to another. c cdotc Level 1 BLAS that computes the scalar product of two vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: getv0.F SID: 2.1 c c\SCCS Information: c FILE: getv0.F SID: 1.7 DATE OF SID: 04/12/01 c c\EndLib c c----------------------------------------------------------------------- c subroutine pcgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) , & rzero = 0.0 ) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj, myid, igen Real & rnorm0 Complex & cnorm, cnorm2 save first, iseed, inits, iter, msglvl, orth, rnorm0 c Complex & cnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, cgemv, pclarnv, pcvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & pscnorm2, slapy2 Complex & cdotc external cdotc, pscnorm2, slapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then c c %-----------------------------------% c | Generate a seed on each processor | c | using process id (myid). | c | Note: the seed must be between 1 | c | and 4095. iseed(4) must be odd. | c %-----------------------------------% c call MPI_COMM_RANK(comm, myid, ierr) igen = 1000 + 2*myid + 1 if (igen .gt. 4095) then write(0,*) 'Error in p_getv0: seed exceeds 4095!' end if c iseed(1) = igen/1000 igen = mod(igen,1000) iseed(2) = igen/100 igen = mod(igen,100) iseed(3) = igen/10 iseed(4) = mod(igen,10) c inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pclarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call ccopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm_buf = cdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) rnorm0 = sqrt(slapy2(real (cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm0 = pscnorm2( comm, n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett`s book, page 107 and in Gragg and Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call cgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl, j-1, & MPI_COMPLEX, MPI_SUM, comm, ierr) call cgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm_buf = cdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) rnorm = sqrt(slapy2(real (cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5 ) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then cnorm2 = cmplx(rnorm,rzero) call pcvout (comm, logfil, 1, cnorm2, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pcvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pcgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pclarnv.f000066400000000000000000000036201260666001200173310ustar00rootroot00000000000000c\BeginDoc c c\Name: pclarnv c c Message Passing Layer: MPI c c\Description: c c Parallel Version of ARPACK utility routine clarnv c c PCLARNV returns a vector of n (nloc) random Complex numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM MPI Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Complex array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine clarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine CLARNV to generate random c Complex numbers from a uniform or normal distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.3 DATE OF SID: 04/17/99 c c----------------------------------------------------------------------- c subroutine pclarnv( comm, idist, iseed, n, x ) c integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Complex & x( * ) c .. c .. External Subroutines .. external clarnv c .. c .. Executable Statements .. c call clarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcnaitr.f000066400000000000000000000770071260666001200173360ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pcnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pcnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pcnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Complex work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pcgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c clanhs LAPACK routine that computes various norms of a matrix. c clascl LAPACK routine for careful scaling of a matrix. c slabad LAPACK routine for defining the underflow and overflow c limits c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of c two vectors. c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c pscnorm2 Parallel version of Level 1 BLAS that computes the c norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: naitr.F SID: 2.1 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pcnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone, rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0, rzero = 0.0) c c %--------------% c | Local Arrays | c %--------------% c Real & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c Complex & cnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cscal, cgemv, pcgetv0, slabad, & csscal, pcvout, pcmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex & cdotc Real & pslamch, pscnorm2, clanhs, slapy2 external cdotc, pscnorm2, clanhs, pslamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------% c unfl = pslamch(comm, 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pcgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pcvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pcgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call ccopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call csscal (n, temp1, v(1,j), 1) call csscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine clascl | c %-----------------------------------------% c call clascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call clascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call ccopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call ccopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm_buf = cdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) wnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = pscnorm2(comm, n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call MPI_ALLREDUCE( workl, h(1,j), j, & MPI_COMPLEX, MPI_SUM, comm, ierr) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = cmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm_buf = cdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) rnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call psvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call pcvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_COMPLEX, MPI_SUM, comm, ierr) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call caxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm_buf = cdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) rnorm1 = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = pscnorm2(comm, n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call psvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %--------------------------------------------% c tst1 = slapy2(real(h(i,i)),aimag(h(i,i))) & + slapy2(real(h(i+1,i+1)), aimag(h(i+1,i+1))) if( tst1.eq.real(zero) ) & tst1 = clanhs( '1', k+np, h, ldh, workd(n+1) ) if( slapy2(real(h(i+1,i)),aimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pcmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pcnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcnapps.f000066400000000000000000000431161260666001200173340ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnapps c c Message Passing Layer: MPI c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pcnapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex array of length NP. (INPUT) c The shifts to be applied. c c V Complex N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clanhs LAPACK routine that computes various norms of a matrix. c clartg LAPACK Givens rotation construction routine. c claset LAPACK matrix initialization routine. c slabad LAPACK routine for defining the underflow and overflow c limits. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another. c cscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: napps.F SID: 2.1 c c\SCCS Information: c FILE: napps.F SID: 1.4 DATE OF SID: 10/25/03 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine clahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex & cdum, f, g, h11, h21, r, s, sigma, t Real & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cgemv, cscal, clacpy, clartg, & pcvout, claset, slabad, pcmout, arscnd, pivout c c %--------------------% c | External Functions | c %--------------------% c Real & clanhs, pslamch, slapy2 external clanhs, pslamch, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, aimag, conjg, cmplx, max, min, real c c %---------------------% c | Statement Functions | c %---------------------% c Real & cabs1 cabs1( cdum ) = abs( real( cdum ) ) + abs( aimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------------% c unfl = pslamch( comm, 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call claset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pcvout (comm, logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %----------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = clanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(real(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pcvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call clartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( real( h(j+1,j) ) .lt. rzero .or. & aimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / slapy2(real(h(j+1,j)),aimag(h(j+1,j))) call cscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call cscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call cscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = cmplx( real( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = clanhs( '1', kev, h, ldh, workl ) if( real( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call cgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call cgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call ccopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call clacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call ccopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call cscal (n, q(kplusp,kev), resid, 1) if ( real( h(kev+1,kev) ) .gt. rzero ) & call caxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pcvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pcvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pcmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %----------------% c | End of pcnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcnaup2.f000066400000000000000000000723121260666001200172400ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by pcnaupd. c c\Usage: c call pcnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pcnaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pcnaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in PCNAUPD. c c RWORK Real work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pcgetv0 Parallel ARPACK initial vector generation routine. c pcnaitr Parallel ARPACK Arnoldi factorization routine. c pcnapps Parallel ARPACK application of implicit shifts routine. c pcneigh Parallel ARPACK compute Ritz values and error bounds routine. c pcngets Parallel ARPACK reorder Ritz values and error bounds routine. c csortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c psvout ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of two vectors. c cswap Level 1 BLAS that swaps two vectors. c pscnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c FILE: naup2.F SID: 1.7 DATE OF SID: 10/25/03 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Real & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm, getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex & cmpnorm Real & rnorm, eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0, eps23 c Real & cmpnorm_buf c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, pcgetv0, pcnaitr, pcneigh, pcngets, pcnapps, & csortc, cswap, pcmout, pcvout, pivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex & cdotc Real & pscnorm2, pslamch, slapy2 external cdotc, pscnorm2, pslamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real, min, max, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pcgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pcnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pcnapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pcnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pcneigh ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from pcneigh. | c %--------------------------------------------------% c call ccopy(kplusp,ritz,1,workl(kplusp**2+1),1) call ccopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call pcngets ( comm, ishift, which, nev, np, ritz, & bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, slapy2( real(ritz(np+i)), & aimag(ritz(np+i)) ) ) if ( slapy2(real(bounds(np+i)),aimag(bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call pcvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call pcvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call pcvout(comm, logfil, kplusp, & workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call pcvout(comm, logfil, kplusp, & workl(kplusp**2+kplusp+1), ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to pcneupd if needed | c %------------------------------------------% c h(3,1) = cmplx(rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call csortc(wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, slapy2( real(ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call csortc(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, slapy2( real(ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call csortc(which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call pcvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call pcvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pcngets (comm, ishift, which, nev, np, ritz, & bounds) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pcvout (comm, logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call pcvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call ccopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pcvout (comm, logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call pcvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pcnapps(comm, n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pcnaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm_buf = cdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cmpnorm_buf, cmpnorm, 1, & MPI_COMPLEX, MPI_SUM, comm, ierr ) rnorm = sqrt(slapy2(real(cmpnorm),aimag(cmpnorm))) else if (bmat .eq. 'I') then rnorm = pscnorm2(comm, n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pcmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pcnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcnaupd.f000066400000000000000000000672211260666001200173250ustar00rootroot00000000000000c\BeginDoc c c\Name: pcnaupd c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then ssaupd or snaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pcnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pcnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pcnaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pcnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = pslamch(comm, 'EPS') (machine precision as computed c by the ScaLAPACK auxiliary subroutine pslamch). c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below) c c V Complex array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of pcnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by pcneupd. See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c cneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Real work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine pcneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call pcneupd immediately following c completion of pcnaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pcnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c cstatn ARPACK routine that initializes the timing variables. c pivout Parallel ARPACK utility routine that prints integers. c pcvout Parallel ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c pslamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pcnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, rwork, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Real & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pcnaup2, pcvout, pivout, arscnd, cstatn c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call cstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0 ) tol = pslamch(comm, 'EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine pcneigh called | c | by pcnaup2. Subroutine pcneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pcnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pcnaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pcvout (comm, logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call pcvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pcnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcneigh.f000066400000000000000000000205271260666001200173060ustar00rootroot00000000000000c\BeginDoc c c\Name: pcneigh c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pcneigh c ( COMM, RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Real work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from clahqr or ctrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c psvout Parallel ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c ccopy Level 1 BLAS that copies one vector to another. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: neigh.F SID: 2.1 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pcneigh (comm, rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Real & rwork(n) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex & vl(1) Real & temp c c %----------------------% c | External Subroutines | c %----------------------% c external clacpy, clahqr, csscal, ctrevc, ccopy, & pcmout, pcvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2 external scnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call pcmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | clahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call clacpy ('All', n, n, h, ldh, workl, n) call claset ('All', n, n, zero, one, q, ldq) call clahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call ccopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call pcvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ctrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = scnrm2( n, q(1,j), 1 ) call csscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call ccopy(n, q(n,1), ldq, workl, 1) call pcvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call ccopy(n, q(n,1), n, bounds, 1) call csscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call pcvout (comm, logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call pcvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pcneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcneupd.f000066400000000000000000001046461260666001200173340ustar00rootroot00000000000000c\BeginDoc c c\Name: pcneupd c c Message Passing Layer: MPI c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PCNAUPD. PCNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of PCNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of PCNAUPD. c c\Usage: c call pcneupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PCNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PCNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to CNEUPD following the last call c to PCNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PCNAUPD and the call to CNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PCNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c PCNAUPD. They are not changed by PCNEUPD. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by PCNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PCNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ctrsen. c Re-enter subroutine pcneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ctrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PCNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: CNEUPD got a different count of the number of converged c Ritz values than CNAUPD got. This indicates the user c probably made an error in passing data from CNAUPD to c CNEUPD or that the data was modified before entering c CNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pcmout Parallel ARPACK utility routine that prints matrices c pcvout Parallel ARPACK utility routine that prints vectors. c cgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ctrsen LAPACK routine that re-orders the Schur form. c cunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c pslamch ScaLAPACK routine that determines machine constants. c ctrmm Level 3 BLAS matrix times an upper triangular matrix. c cgeru Level 2 BLAS rank one update to a matrix. c ccopy Level 1 BLAS that copies one vector to another . c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: neupd.F SID: 2.2 c c\SCCS Information: c FILE: neupd.F SID: 1.9 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pcneupd & ( comm , rvec , howmny, select, d , & z , ldz , sigma , workev, bmat , & n , which , nev , tol , resid, & ncv , v , ldv , iparam, ipntr, & workd, workl , lworkl, rwork , info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex & sigma Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & rwork(ncv) Complex & d(nev) , resid(n) , v(ldv,ncv) , & z(ldz, nev), workd(3*n), workl(lworkl), & workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift Complex & rnorm, temp, vl(1) Real & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy ,cgeru,cgeqr2,clacpy,pcmout, & cunm2r,ctrmm,pcvout,pivout, & clahqr c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2,pslamch,slapy2 external scnrm2,pslamch,slapy2 c Complex & cdotc external cdotc c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by CNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pcvout(comm, logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call pcvout(comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pcngets(comm, ishift, which , & nev , np , workl(irz), & workl(bounds)) c if (msglvl .gt. 2) then call pcvout(comm,logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call pcvout(comm,logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & slapy2 ( real (workl(irz+ncv-j)), & aimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & slapy2( real (workl(ibd+jj-1)), & aimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine clahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by PCNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call ccopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call claset('All', ncv, ncv, zero, one, workl(invsub), ldq) call clahqr(.true. , .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr ) call ccopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pcvout(comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call pcvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pcmout(comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ctrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv , conds , sep , & workev, ncv, ierr) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pcvout (comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call pcmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call ccopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call ccopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call cgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using cunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call cunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call clacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( real( workl(invsub+(j-1)*ldq+j-1) ) .lt. & real(zero) ) then call cscal(nconv, -one, workl(iuptri+j-1), ldq) call cscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ctrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr ) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = scnrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = real(one) / rtemp call csscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = cdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call ccopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call pcvout(comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pcmout(comm, logfil, nconv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call ccopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ctrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PCNAUPD into D. | c %--------------------------------------------------% c call ccopy(nconv, workl(ritz), 1, d, 1) call ccopy(nconv, workl(ritz), 1, workl(iheig), 1) call ccopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pcvout (comm, logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call pcvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call pcvout (comm, logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call pcvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call cgeru(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of pcneupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pcngets.f000066400000000000000000000134661260666001200173400ustar00rootroot00000000000000c\BeginDoc c c\Name: pcngets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pcngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c csortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pcvout Parallel ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: ngets.F SID: 2.1 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine pcngets ( comm, ishift, which, kev, np, ritz, bounds) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external pcvout, csortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call csortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pcnapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call csortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pcvout (comm, logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call pcvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pcngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdgetv0.f000066400000000000000000000335351260666001200172450ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdgetv0 c c Message Passing Layer: MPI c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pdgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pdgetv0 is called. c It should be set to 1 on the initial call to pdgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Double precision N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Double precision work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine for vector output. c pdlarnv Parallel wrapper for LAPACK routine dlarnv (generates a random vector). c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: getv0.F SID: 2.3 c c\SCCS Information: c FILE: getv0.F SID: 1.4 DATE OF SID: 3/19/97 c c\EndLib c c----------------------------------------------------------------------- c subroutine pdgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Double precision & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c Double precision & rnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external pdlarnv, pdvout, dcopy, dgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2 external ddot, pdnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pdlarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call dcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c first = .FALSE. if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm0, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = pdnorm2( comm, n, resid, 1 ) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call dgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl, j-1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) call dgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pdvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdlamch10.f000066400000000000000000000060411260666001200174350ustar00rootroot00000000000000 DOUBLE PRECISION FUNCTION PDLAMCH10( ICTXT, CMACH ) include "mpif.h" * * -- ScaLAPACK auxilliary routine (version 1.0) -- * University of Tennessee, Knoxville, Oak Ridge National Laboratory, * and University of California, Berkeley. * February 28, 1995 * * The name has been changed in order to avoid symbol collision with * the newer version of PDLAMCH in Scalapack which can not be used * with MPI context. * * .. Scalar Arguments .. CHARACTER CMACH INTEGER ICTXT * .. * * Purpose * ======= * * PDLAMCH determines double precision machine parameters. * * Arguments * ========= * * ICTXT (global input) INTEGER * The MPI context handle in which the computation takes * place. * * CMACH (global input) CHARACTER*1 * Specifies the value to be returned by PDLAMCH: * = 'E' or 'e', PDLAMCH := eps * = 'S' or 's , PDLAMCH := sfmin * = 'B' or 'b', PDLAMCH := base * = 'P' or 'p', PDLAMCH := eps*base * = 'N' or 'n', PDLAMCH := t * = 'R' or 'r', PDLAMCH := rnd * = 'M' or 'm', PDLAMCH := emin * = 'U' or 'u', PDLAMCH := rmin * = 'L' or 'l', PDLAMCH := emax * = 'O' or 'o', PDLAMCH := rmax * * where * * eps = relative machine precision * sfmin = safe minimum, such that 1/sfmin does not overflow * base = base of the machine * prec = eps*base * t = number of (base) digits in the mantissa * rnd = 1.0 when rounding occurs in addition, 0.0 otherwise * emin = minimum exponent before (gradual) underflow * rmin = underflow threshold - base**(emin-1) * emax = largest exponent before overflow * rmax = overflow threshold - (base**emax)*(1-eps) * * ===================================================================== * * .. Local Scalars .. INTEGER IDUMM DOUBLE PRECISION TEMP, TEMP1 * .. * .. External Subroutines .. * EXTERNAL DGAMN2D, DGAMX2D * .. * .. External Functions .. LOGICAL LSAME DOUBLE PRECISION DLAMCH EXTERNAL DLAMCH, LSAME * .. * .. Executable Statements .. * TEMP1 = DLAMCH( CMACH ) * IF( LSAME( CMACH, 'E' ).OR.LSAME( CMACH, 'S' ).OR. $ LSAME( CMACH, 'M' ).OR.LSAME( CMACH, 'U' ) ) THEN CALL MPI_ALLREDUCE( TEMP1, TEMP, 1, MPI_DOUBLE_PRECISION, $ MPI_MAX, ICTXT, IDUMM ) * CALL DGAMX2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, * $ IDUMM, 1, -1, IDUMM ) ELSE IF( LSAME( CMACH, 'L' ).OR.LSAME( CMACH, 'O' ) ) THEN CALL MPI_ALLREDUCE( TEMP1, TEMP, 1, MPI_DOUBLE_PRECISION, $ MPI_MIN, ICTXT, IDUMM ) * CALL DGAMN2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, * $ IDUMM, 1, -1, IDUMM ) ELSE TEMP = TEMP1 END IF * PDLAMCH = TEMP * * End of PDLAMCH * END arpack-ng-3.3.0/PARPACK/SRC/MPI/pdlarnv.f000066400000000000000000000037221260666001200173350ustar00rootroot00000000000000c\BeginDoc c c\Name: pdlarnv c c Message Passing Layer: MPI c c\Description: c c Parallel Version of ARPACK utility routine dlarnv c c PSLARNV returns a vector of n (nloc) random real numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM MPI Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Double precision array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine dlarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine SLARNV to generate random c real numbers from a uniform (0,1) distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.4 DATE OF SID: 04/16/99 c c----------------------------------------------------------------------- c subroutine pdlarnv( comm, idist, iseed, n, x ) c include 'mpif.h' c c .. MPI VARIABLES AND FUNCTIONS .. integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Double precision & x( * ) c .. c .. External Subroutines .. external dlarnv c .. c .. Executable Statements .. c call dlarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdnaitr.f000066400000000000000000000762151260666001200173370ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdnaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pdnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pdnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pdnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pdgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout Parallel ARPACK utility routine that prints vectors. c dlabad LAPACK routine that computes machine constants. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dlanhs LAPACK routine that computes various norms of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naitr.F SID: 2.2 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pdnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c Double precision & rnorm_buf c c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, pdgetv0, dlabad, & pdvout, pdmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, dlanhs, pdlamch10 external ddot, pdnorm2, dlanhs, pdlamch10 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------% c unfl = pdlamch10(comm, 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = pdlamch10( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pdgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pdgetv0 ( comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call MPI_ALLREDUCE( workl, h(1,j), j, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call pdvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call daxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm1, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = pdnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pdmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pdnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdnapps.f000066400000000000000000000562401260666001200173370ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdnapps c c Message Passing Layer: MPI c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pdnapps c ( COMM, N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Double precision array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to pdnapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c dlabad LAPACK routine that computes machine constants. c dlacpy LAPACK matrix copy routine. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlanhs LAPACK routine that computes various norms of a matrix. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlarf LAPACK routine that applies Householder reflection to c a matrix. c dlarfg LAPACK Householder reflection construction routine. c dlartg LAPACK Givens rotation construction routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another . c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: napps.F SID: 2.2 c c\SCCS Information: c FILE: napps.F SID: 1.5 DATE OF SID: 03/19/97 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine dlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnapps & ( comm, n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, & q, ldq, workl, workd ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Double precision & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlarf, dlarfg, dlartg, & dlaset, dlabad, arscnd, pivout, pdvout, pdmout c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch10, dlanhs, dlapy2 external pdlamch10, dlanhs, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------------% c unfl = pdlamch10( comm, 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = pdlamch10( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pdvout (comm, logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call pdvout (comm, logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pdvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call dlartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = dlapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call dlarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call dlarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call dlarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call dlarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call dscal( kplusp-j+1, -one, h(j+1,j), ldh ) call dscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call dscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %---------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %---------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call daxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pdvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pdmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %----------------% c | End of pdnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdnaup2.f000066400000000000000000000772471260666001200172550ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by pdnaupd . c c\Usage: c call pdnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pdnaupd . c MODE, ISHIFT, MXITER: see the definition of IPARAM in pdnaupd . c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from dneigh . c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pdgetv0 Parallel ARPACK initial vector generation routine. c pdnaitr Parallel ARPACK Arnoldi factorization routine. c pdnapps Parallel ARPACK application of implicit shifts routine. c dnconv ARPACK convergence of Ritz values routine. c pdneigh Parallel ARPACK compute Ritz values and error bounds routine. c pdngets Parallel ARPACK reorder Ritz values and error bounds routine. c dsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Revision history: c Starting Point: Serial Code FILE: naup2.F SID: 2.2 c c\SCCS Information: c FILE: naup2.F SID: 1.5 DATE OF SID: 06/01/00 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Double precision & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv, & j Double precision & rnorm , temp , eps23 save cnorm , getv0, initv , update, ushift, & rnorm , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , eps23 , numcnv c Double precision & rnorm_buf c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , pdgetv0 , pdnaitr , dnconv , & pdneigh , pdngets , pdnapps , & pdvout , pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot , pdnorm2 , dlapy2 , pdlamch10 external ddot , pdnorm2 , dlapy2 , pdlamch10 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = pdlamch10 (comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pdgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pdnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pdnapps . | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pdnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pdneigh ( comm, rnorm, kplusp, h, ldh, ritzr, ritzi, & bounds, q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from pdneigh . | c %----------------------------------------------------% c call dcopy (kplusp, ritzr, 1, workl(kplusp**2+1), 1) call dcopy (kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call dcopy (kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of pdngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call pdngets ( comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call dnconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call pivout (comm, logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call pdvout (comm, logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call pdvout (comm, logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call dvout (logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with dngets , we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in dngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call dsortc (wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call dsortc (which, .true., nconv, ritzr, ritzi, bounds) c c if (msglvl .gt. 1) then call dvout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call dvout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call dvout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pdngets (comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pdvout (comm, logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call pdvout (comm, logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call pdvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call dcopy (np, workl, 1, ritzr, 1) call dcopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pdvout (comm, logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call pdvout (comm, logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call pdvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pdnapps (comm, n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pdnaitr . | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_DOUBLE_PRECISION , MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2 ( comm, n, resid, 1 ) end if cnorm = .false. c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pdmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pdnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdnaupd.f000066400000000000000000000732451260666001200173310ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnaupd c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine dsaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pdnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pdnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdnaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pdnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Double precision array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of pdnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pdnaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by dneupd . See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c pdneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine dneupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine dneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call dneupd immediately following c completion of pdnaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Double precision resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Double precision resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pdnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.9 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pdnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external pdnaup2 , pdvout , pivout, arscnd, dstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch10 external pdlamch10 c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pdlamch10 (comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine pdneigh called | c | by pdnaup2 . Subroutine dneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pdnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pdnaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pdvout (comm, logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call pdvout (comm, logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call pdvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pdnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdneigh.f000066400000000000000000000251461260666001200173110ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdneigh c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pdneigh c ( COMM, RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Double precision N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Double precision N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from dlaqrb or dtrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dlahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dlacpy LAPACK matrix copy routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another . c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neigh.F SID: 2.2 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdneigh ( comm, rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Double precision & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dlacpy, dlahqr, dtrevc, dvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call pdmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | dlahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call dlacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = 1 call dlahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call dtrevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = dnrm2( n, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2( dnrm2( n, q(1,i), 1 ), & dnrm2( n, q(1,i+1), 1 ) ) call dscal ( n, one / temp, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call dgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * dlapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call pdvout (comm, logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call pdvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdneupd.f000066400000000000000000001270631260666001200173330ustar00rootroot00000000000000c\BeginDoc c c\Name: pdneupd c c Message Passing Layer: MPI c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PDNAUPD . PDNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine PDNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of PDNAUPD . c c\Usage: c call pdneupd c ( COMM, RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Double precision array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c PDNAUPD . A further computation must be performed by the user c to transform the Ritz values computed for OP by PDNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Double precision array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Double precision N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PDNAUPD . In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Double precision work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PDNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PDNEUPD following the last call c to PDNAUPD . These arguments MUST NOT BE MODIFIED between c the the last call to PDNAUPD and the call to PDNEUPD . c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Double precision N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PDNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c PDNAUPD . They are not changed by PDNEUPD . c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointers into WORKL for addresses c of the above information computed by PDNEUPD . c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PDNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine dlahqr c could not be reordered by LAPACK routine dtrsen . c Re-enter subroutine pdneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine dlahqr . c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine dtrevc . c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PDNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: PDNEUPD got a different count of the number of converged c Ritz values than PDNAUPD got. This indicates the user c probably made an error in passing data from PDNAUPD to c PDNEUPD or that the data was modified before entering c PDNEUPD . c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pdmout Parallel ARPACK utility routine that prints matrices c pdvout Parallel ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c dlahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK matrix initialization routine. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c dtrsen LAPACK routine that re-orders the Schur form. c dtrmm Level 3 BLAS matrix times an upper triangular matrix. c dger Level 2 BLAS rank one update to a matrix. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X` denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by PDNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c Z(:,I)` * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c Z(:,I)` * A * Z(:,I) + Z(:,I+1)` * A * Z(:,I+1), c Z(:,I)` * A * Z(:,I+1) - Z(:,I+1)` * A * Z(:,I), respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute V(:,1:IPARAM(5))` * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neupd.F SID: 2.3 c c\SCCS Information: c FILE: neupd.F SID: 1.8 DATE OF SID: 04/10/01 c c\EndLib c c----------------------------------------------------------------------- subroutine pdneupd & (comm , rvec , howmny, select, dr , di , & z , ldz , sigmar, sigmai, workev, bmat, & n , which, nev , tol , resid , & ncv , v , ldv , iparam, ipntr , & workd, workl, lworkl, info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & dr(nev+1) , di(nev+1) , resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr, ih, ihbds, & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj logical reord Double precision & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2 , dlacpy , & dlahqr , dlaset , pdmout , dorm2r , & dtrevc , dtrmm , dtrsen , dscal , & pdvout , pivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2 , dnrm2 , pdlamch10 external dlapy2 , dnrm2 , pdlamch10 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch10 (comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by PDNEUPD . | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call pdvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call pdvout (comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pdngets (comm , ishift , which , & nev , np , workl(irr), & workl(iri), workl(bounds), & workl , workl(np+1)) c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call pdvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call pdvout (comm, logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & dlapy2 ( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine dlahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by PDNAUPD . | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ldh*ncv, workl(ih), 1, workl(iuptri), 1) call dlaset ('All', ncv, ncv, zero, one, workl(invsub), ldq) call dlahqr (.true. , .true. , ncv, 1 , & ncv , workl(iuptri), ldh, workl(iheigr), & workl(iheigi), 1 , ncv, workl(invsub), & ldq , ierr) call dcopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pdvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call pdvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call pdvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call dtrsen ('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheigr), & workl(iheigi), nconv , conds , & sep , workl(ihbds) , ncv , & iwork , 1 , ierr ) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call pdvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call dcopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using dorm2r . | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call dlacpy ('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call dscal (nconv, -one, workl(iuptri+j-1), ldq) call dscal (nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call dtrevc ('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = dnrm2 ( ncv, workl(invsub+(j-1)*ldq), 1 ) call dscal ( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2 (dnrm2 (ncv, & workl(invsub+(j-1)*ldq), & 1 ), & dnrm2 (ncv, & workl(invsub+j*ldq), & 1) & ) call dscal (ncv, one/temp, & workl(invsub+(j-1)*ldq), 1) call dscal (ncv, one/temp, & workl(invsub+j*ldq), 1) iconj = 1 else iconj = 0 end if c end if c 40 continue c call dgemv ('T' , ncv , nconv, & one , workl(invsub), ldq , & workl(ihbds), 1 , zero , & workev , 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = dlapy2 (workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pdmout (comm, logfil, ncv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call dcopy (nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call dtrmm ('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PDNAUPD into DR and DI | c %------------------------------------------------------% c call dcopy (nconv, workl(ritzr), 1, dr, 1) call dcopy (nconv, workl(ritzi), 1, di, 1) call dcopy (nconv, workl(ritzr), 1, workl(iheigr), 1) call dcopy (nconv, workl(ritzi), 1, workl(iheigi), 1) call dcopy (nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) do 50 k=1, ncv temp = dlapy2 (workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = dlapy2 (workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1) / temp / temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1) / temp / temp & + sigmai 80 continue c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call pdvout (comm, logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call pdvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call pdvout (comm, logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call pdvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheigr+j-1) else if (iconj .eq. 0) then temp = dlapy2 ( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call dger (n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of PDNEUPD | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdngets.f000066400000000000000000000202641260666001200173330ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdngets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pdngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Double precision array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortc ARPACK sorting routine. c dcopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ngets.F SID: 2.2 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine pdngets & ( comm, ishift, which, kev, np, ritzr, ritzi, & bounds, shiftr, shifti ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dsortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call dsortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call dsortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call dsortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine pdnapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call dsortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pdvout (comm, logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call pdvout (comm, logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call pdvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pdngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdnorm2.f000066400000000000000000000035331260666001200172500ustar00rootroot00000000000000c\BeginDoc c c\Name: pdnorm2 c c Message Passing Layer: MPI c c\Description: c c\Usage: c call pdnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 2/22/96 c c----------------------------------------------------------------------- c Double precision function pdnorm2 ( comm, n, x, inc ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm, ierr c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & x(n) c c %---------------% c | Local Scalars | c %---------------% c Double precision & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Double precision & dnrm2 External dnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pdnorm2 = dnrm2( n, x, inc) c buf = pdnorm2 call MPI_ALLREDUCE( buf, max, 1, MPI_DOUBLE_PRECISION, & MPI_MAX, comm, ierr ) if ( max .eq. zero ) then pdnorm2 = zero else buf = (pdnorm2/max)**2.0 call MPI_ALLREDUCE( buf, pdnorm2, 1, MPI_DOUBLE_PRECISION, & MPI_SUM, comm, ierr ) pdnorm2 = max * sqrt(abs(pdnorm2)) endif c c %----------------% c | End of pdnorm2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdsaitr.f000066400000000000000000000771751260666001200173520ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pdsaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pdsaitr c ( COMM, IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See pdsaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c WORKL Double precision work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c pdgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c pdmout Parallel ARPACK utility routine that prints matrices. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saitr.F SID: 2.3 c c\SCCS Information: c FILE: saitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pdsaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaitr & (comm, ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, infol, & jj Double precision & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c Double precision & rnorm_buf c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, pdgetv0, pdvout, pdmout, & dlascl, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, pdlamch10 external ddot, pdnorm2, pdlamch10 c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = pdlamch10(comm,'safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pdgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pdgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c rnorm_buf = ddot (n, resid, 1, workd(ivj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call dgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) else if (mode .eq. 2) then call dgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv('N', n, j, -one, v, ldv, workl(1), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workl(j) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workl(j) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm1, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = pdnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call pdvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call dscal(n, -one, v(1,j+1), 1) else call dscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call pdvout (comm, logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call pdvout (comm, logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pdsaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdsapps.f000066400000000000000000000446541260666001200173520ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pdsapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Double precision array of length NP. (INPUT) c The shifts to be applied. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlartg LAPACK Givens rotation construction routine. c dlacpy LAPACK matrix copy routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sapps.F SID: 2.4 c c\SCCS Information: c FILE: sapps.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Double precision & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlartg, dlaset, pdvout, & pivout, arscnd, dgemv c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch10 external pdlamch10 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = pdlamch10(comm, 'Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call pdvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call dscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pdvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call daxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call pdvout (comm, logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call pdvout (comm, logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call pdvout (comm, logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %----------------% c | End of pdsapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdsaup2.f000066400000000000000000001011621260666001200172420ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by pdsaupd. c c\Usage: c call pdsaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pdsaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pdsaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the second column c of H starting at H(1,2). If pdsaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Double precision array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in pdsaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c pdgetv0 Parallel ARPACK initial vector generation routine. c pdsaitr Parallel ARPACK Lanczos factorization routine. c pdsapps Parallel ARPACK application of implicit shifts routine. c dsconv ARPACK convergence of Ritz values routine. c pdseigt Parallel ARPACK compute Ritz values and error bounds routine. c pdsgets Parallel ARPACK reorder Ritz values and error bounds routine. c dsortr ARPACK sorting routine. c sstrqb ARPACK routine that computes all eigenvalues and the c last component of the eigenvectors of a symmetric c tridiagonal matrix using the implicit QL or QR method. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c pdnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saup2.F SID: 2.4 c c\SCCS Information: c FILE: saup2.F SID: 1.5 DATE OF SID: 05/20/98 c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Double precision & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c Double precision & rnorm_buf c c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, pdgetv0, pdsaitr, dscal, dsconv, & pdseigt, pdsgets, pdsapps, & dsortr, pdvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, pdnorm2, pdlamch10 external ddot, pdnorm2, pdlamch10 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pdlamch10(comm, 'Epsilon-Machine') eps23 = eps23**(2.0/3.0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %---------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %---------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pdgetv0 ( comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call pdsaitr (comm, ido, bmat, n, 0, nev0, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pdsaitr was unable to build an Lanczos factorization| c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call pivout (comm, logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call pdsaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pdsaitr was unable to build an Lanczos factorization| c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call pdseigt ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call dcopy(kplusp, ritz, 1, workl(kplusp+1), 1) call dcopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call pdsgets ( comm, ishift, which, nev, np, ritz, & bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(np+1), 1) call dsconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call pdvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call dsortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then call dswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call dswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call dsortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call dsortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call pdvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call pdvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pdsgets ( comm, ishift, which, nev, np, & ritz, bounds, workl) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_saup2: NEV and NP .') call pdvout (comm, logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call pdvout (comm, logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, pdsgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call dcopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call pdvout (comm, logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call pdvout (comm, logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After pdsapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call pdsapps ( comm, n, nev, np, ritz, v, ldv, h, ldh, resid, & q, ldq, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pdsaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm_buf = ddot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_DOUBLE_PRECISION, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = pdnorm2( comm, n, resid, 1 ) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call pdvout (comm, logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call pdvout (comm, logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %----------------% c | End of pdsaup2 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdsaupd.f000066400000000000000000000715701260666001200173350ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsaupd c c Message Passing Layer: MPI c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pdsaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pdsaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pdsaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pdsaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Double precision N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of pdsaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pdsaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by pdseupd . See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c pdseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine pdseupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine dsteqr . c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine pdseupd . c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call pdseupd immediately following completion c of pdsaupd . This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c pdsaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c dstats ARPACK routine that initializes timing and other statistics c variables. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c c\Authors c Kristi Maschhoff ( Parallel Code ) c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saupd.F SID: 2.4 c c\SCCS Information: c FILE: saupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pdsaup2 , pdvout , pivout, arscnd, dstats c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch10 external pdlamch10 c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pdlamch10 (comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call pdsaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pdsaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call pdvout (comm, logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call pdvout (comm, logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.1' , 19x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if end if c 9000 continue c return c c %----------------% c | End of pdsaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdseigt.f000066400000000000000000000130651260666001200173270ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdseigt c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call pdseigt c ( COMM, RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Double precision N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Double precision array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Double precision work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from dstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seigt.F SID: 2.2 c c\SCCS Information: c FILE: seigt.F SID: 1.3 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pdseigt & ( comm, rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dstqrb, pdvout, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call pdvout (comm, logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call pdvout (comm, logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c c call dcopy (n, h(1,2), 1, eig, 1) call dcopy (n-1, h(2,1), 1, workl, 1) call dstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call pdvout (comm, logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %-----------------% c | End of pdseigt | c %-----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdseupd.f000066400000000000000000001036031260666001200173320ustar00rootroot00000000000000c\BeginDoc c c\Name: pdseupd c c Message Passing Layer: MPI c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by PSSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in PSSAUPD documentation.) PSSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine PSSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call pdseupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as workspace. c c D Double precision array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by pdsaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by PSSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Double precision (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to PDNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSSEUPD following the last call c to PSSAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSSAUPD and the call to PSSEUPD. c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c PSSAUPD. They are not changed by PSSEUPD. c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointers into WORKL for addresses c of the above information computed by PSSEUPD. c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c PSSEUPD if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine dsteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: PSSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: DSEUPD got a different count of the number of converged c Ritz values than DSAUPD got. This indicates the user c probably made an error in passing data from DSAUPD to c DSEUPD or that the data was modified before entering c DSEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c dsesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c dsortr dsortr ARPACK sorting routine. c pdnorm2 Parallel ARPACK routine that computes the 2-norm of a vector. c pivout Parallel ARPACK utility routine that prints integers. c pdvout Parallel ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c pdlamch10 ScaLAPACK routine that determines machine constants. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dsteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c dger Level 2 BLAS rank one update to a matrix. c dcopy Level 1 BLAS that copies one vector to another . c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seupd.F SID: 2.4 c c\SCCS Information: c FILE: seupd.F SID: 1.11 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pdseupd & (comm , rvec , howmny, select, d , & z , ldz , sigma , bmat , n , & which , nev , tol , resid , ncv , & v , ldv , iparam, ipntr , workd, & workl , lworkl, info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Double precision & d(nev), resid(n), v(ldv,ncv), z(ldz, nev), & workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Double precision & bnorm2, rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2, dlacpy, dorm2r, dscal, & dsesrt, dsteqr, dswap , pdvout, pivout, dsortr c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdnorm2, pdlamch10 external pdnorm2, pdlamch10 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | pdsaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by pdsaupd and is not | c | modified by pdseupd. | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by pdseupd. | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | dsteqr. Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by dsteqr and by pdseupd. | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pdlamch10(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of pdsaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = pdnorm2(comm, n, workd, 1) end if c if (msglvl .gt. 2) then call pdvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call pdvout(comm, logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irz). Move | c | the corresponding error estimates | c | in workl(bound) accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pdsgets(comm , ishift, which , & nev , np , workl(irz), & workl(bounds), workl) c if (msglvl .gt. 2) then call pdvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call pdvout(comm, logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ncv-1, workl(ih+1) , 1, workl(ihb), 1) call dcopy (ncv , workl(ih+ldh), 1, workl(ihd), 1) c call dsteqr('Identity', ncv , workl(ihd), & workl(ihb), workl(iq), ldq , & workl(iw) , ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call dcopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call pdvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call pdvout (comm, logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if (.not.select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call dcopy(ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call dcopy(ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call dcopy(ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c 30 end if c if (msglvl .gt. 2) then call pdvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call dcopy(nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call dcopy(nconv, workl(ritz), 1, d, 1) call dcopy(ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call dsesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy(ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by pdsaupd. | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call dcopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call dcopy (nconv, workl(ihd), 1, d, 1) call dsortr('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call dsesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy(ncv, workl(bounds), 1, workl(ihb), 1) call dscal(ncv, bnorm2/rnorm, workl(ihb), 1) call dsortr('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call dgeqr2(ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call dorm2r('Right' , 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr ) call dlacpy('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call dorm2r('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr ) c else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by pdsaupd. | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call dscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / ( workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pdvout (comm, logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call pdvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call pdvout (comm, logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call pdvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / (workl(iw+k)-one) 120 continue c end if c if (type .ne. 'REGULR') & call dger(n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %----------------% c | End of pdseupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdsgets.f000066400000000000000000000171561260666001200173460ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pdsgets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pdsgets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Double precision array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Double precision array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortr ARPACK utility sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pdvout Parallel ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c dswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sgets.F SID: 2.3 c c\SCCS Information: c FILE: sgets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pdsgets & ( comm, ishift, which, kev, np, ritz, bounds, shifts ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dswap, dcopy, dsortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call dsortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call dswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call dswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call dsortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pdsapps. | c %-------------------------------------------------------% c call dsortr ('SM', .true., np, bounds, ritz) call dcopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_sgets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_sgets: NP is') call pdvout (comm, logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call pdvout (comm, logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %----------------% c | End of pdsgets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pdznorm2.f000066400000000000000000000035441260666001200174440ustar00rootroot00000000000000c\BeginDoc c c\Name: pdznorm2 c c Message Passing Layer: MPI c c\Description: c c\Usage: c call pdznorm2 ( COMM, N, X, INC ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 3/6/96 c c----------------------------------------------------------------------- c Double precision function pdznorm2 ( comm, n, x, inc ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm, ierr c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & x(n) c c %---------------% c | Local Scalars | c %---------------% c Double precision & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2 External dznrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pdznorm2 = dznrm2( n, x, inc) c buf = pdznorm2 call MPI_ALLREDUCE( buf, max, 1, MPI_DOUBLE_PRECISION, & MPI_MAX, comm, ierr ) if ( max .eq. zero ) then pdznorm2 = zero else buf = (pdznorm2/max)**2.0 call MPI_ALLREDUCE( buf, pdznorm2, 1, MPI_DOUBLE_PRECISION, & MPI_SUM, comm, ierr ) pdznorm2 = max * sqrt(abs(pdznorm2)) endif c c %-----------------% c | End of pdznorm2 | c %-----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pscnorm2.f000066400000000000000000000034451260666001200174340ustar00rootroot00000000000000c\BeginDoc c c\Name: pscnorm2 c c Message Passing Layer: MPI c c\Description: c c\Usage: c call pscnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 3/6/96 c c----------------------------------------------------------------------- c Real function pscnorm2 ( comm, n, x, inc ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm, ierr c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Complex & x(n) c c %---------------% c | Local Scalars | c %---------------% c Real & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2 External scnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c pscnorm2 = scnrm2( n, x, inc) c buf = pscnorm2 call MPI_ALLREDUCE( buf, max, 1, MPI_REAL, & MPI_MAX, comm, ierr ) if ( max .eq. zero ) then pscnorm2 = zero else buf = (pscnorm2/max)**2.0 call MPI_ALLREDUCE( buf, pscnorm2, 1, MPI_REAL, & MPI_SUM, comm, ierr ) pscnorm2 = max * sqrt(abs(pscnorm2)) endif c c %-----------------% c | End of pscnorm2 | c %-----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/psgetv0.f000066400000000000000000000332651260666001200172640ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psgetv0 c c Message Passing Layer: MPI c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call psgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to psgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that psgetv0 is called. c It should be set to 1 on the initial call to psgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Real N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Real work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Real work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine for vector output. c pslarnv Parallel wrapper for LAPACK routine slarnv (generates a random vector). c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: getv0.F SID: 2.3 c c\SCCS Information: c FILE: getv0.F SID: 1.4 DATE OF SID: 3/19/97 c c\EndLib c c----------------------------------------------------------------------- c subroutine psgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Real & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c Real & rnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external pslarnv, psvout, scopy, sgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2 external sdot, psnorm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pslarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call scopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c first = .FALSE. if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm0, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = psnorm2( comm, n, resid, 1 ) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call sgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl, j-1, & MPI_REAL, MPI_SUM, comm, ierr) call sgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call psvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of psgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pslamch.f000066400000000000000000000055401260666001200173160ustar00rootroot00000000000000 REAL FUNCTION PSLAMCH( ICTXT, CMACH ) * include "mpif.h" * -- ScaLAPACK auxilliary routine (version 1.0) -- * University of Tennessee, Knoxville, Oak Ridge National Laboratory, * and University of California, Berkeley. * February 28, 1995 * * .. Scalar Arguments .. CHARACTER CMACH INTEGER ICTXT * .. * * Purpose * ======= * * PSLAMCH determines single precision machine parameters. * * Arguments * ========= * * ICTXT (global input) INTEGER * The BLACS context handle in which the computation takes * place. * * CMACH (global input) CHARACTER*1 * Specifies the value to be returned by PSLAMCH: * = 'E' or 'e', PSLAMCH := eps * = 'S' or 's , PSLAMCH := sfmin * = 'B' or 'b', PSLAMCH := base * = 'P' or 'p', PSLAMCH := eps*base * = 'N' or 'n', PSLAMCH := t * = 'R' or 'r', PSLAMCH := rnd * = 'M' or 'm', PSLAMCH := emin * = 'U' or 'u', PSLAMCH := rmin * = 'L' or 'l', PSLAMCH := emax * = 'O' or 'o', PSLAMCH := rmax * * where * * eps = relative machine precision * sfmin = safe minimum, such that 1/sfmin does not overflow * base = base of the machine * prec = eps*base * t = number of (base) digits in the mantissa * rnd = 1.0 when rounding occurs in addition, 0.0 otherwise * emin = minimum exponent before (gradual) underflow * rmin = underflow threshold - base**(emin-1) * emax = largest exponent before overflow * rmax = overflow threshold - (base**emax)*(1-eps) * * ===================================================================== * * .. Local Scalars .. INTEGER IDUMM REAL TEMP, TEMP1 * .. * .. External Subroutines .. * EXTERNAL SGAMN2D, SGAMX2D * .. * .. External Functions .. LOGICAL LSAME REAL SLAMCH EXTERNAL LSAME, SLAMCH * .. * .. Executable Statements .. * TEMP1 = SLAMCH( CMACH ) * IF( LSAME( CMACH, 'E' ).OR.LSAME( CMACH, 'S' ).OR. $ LSAME( CMACH, 'M' ).OR.LSAME( CMACH, 'U' ) ) THEN CALL MPI_ALLREDUCE( TEMP1, TEMP, 1, MPI_REAL, $ MPI_MAX, ICTXT, IDUMM ) * CALL SGAMX2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, * $ IDUMM, 1, -1, IDUMM ) ELSE IF( LSAME( CMACH, 'L' ).OR.LSAME( CMACH, 'O' ) ) THEN CALL MPI_ALLREDUCE( TEMP1, TEMP, 1, MPI_REAL, $ MPI_MIN, ICTXT, IDUMM ) * CALL SGAMN2D( ICTXT, 'All', ' ', 1, 1, TEMP, 1, IDUMM, * $ IDUMM, 1, -1, IDUMM ) ELSE TEMP = TEMP1 END IF * PSLAMCH = TEMP * * End of PSLAMCH * END arpack-ng-3.3.0/PARPACK/SRC/MPI/pslarnv.f000066400000000000000000000036721260666001200173600ustar00rootroot00000000000000c\BeginDoc c c\Name: pslarnv c c Message Passing Layer: MPI c c\Description: c c Parallel Version of ARPACK utility routine slarnv c c PSLARNV returns a vector of n (nloc) random real numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM MPI Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Real array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine slarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine SLARNV to generate random c real numbers from a uniform (0,1) distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.4 DATE OF SID: 04/16/99 c c----------------------------------------------------------------------- c subroutine pslarnv( comm, idist, iseed, n, x ) c include 'mpif.h' c c .. MPI VARIABLES AND FUNCTIONS .. integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Real & x( * ) c .. c .. External Subroutines .. external slarnv c .. c .. Executable Statements .. c call slarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/psnaitr.f000066400000000000000000000756541260666001200173640ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psnaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in psnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call psnaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See psnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Real work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c psgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psmout Parallel ARPACK utility routine that prints matrices c psvout Parallel ARPACK utility routine that prints vectors. c slabad LAPACK routine that computes machine constants. c pslamch ScaLAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c slanhs LAPACK routine that computes various norms of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naitr.F SID: 2.2 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in psnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c Real & rnorm_buf c c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, psgetv0, slabad, & psvout, psmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, slanhs, pslamch external sdot, psnorm2, slanhs, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------% c unfl = pslamch(comm, 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | psgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call psvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call psgetv0 ( comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call MPI_ALLREDUCE( workl, h(1,j), j, & MPI_REAL, MPI_SUM, comm, ierr) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call psvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_REAL, MPI_SUM, comm, ierr) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call saxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm1, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = psnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call psmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of psnaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psnapps.f000066400000000000000000000560221260666001200173540ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psnapps c c Message Passing Layer: MPI c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call psnapps c ( COMM, N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Real array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to psnapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c slabad LAPACK routine that computes machine constants. c slacpy LAPACK matrix copy routine. c pslamch ScaLAPACK routine that determines machine constants. c slanhs LAPACK routine that computes various norms of a matrix. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slarf LAPACK routine that applies Householder reflection to c a matrix. c slarfg LAPACK Householder reflection construction routine. c slartg LAPACK Givens rotation construction routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another . c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: napps.F SID: 2.2 c c\SCCS Information: c FILE: napps.F SID: 1.5 DATE OF SID: 03/19/97 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine slahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine psnapps & ( comm, n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, & q, ldq, workl, workd ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Real & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slarf, slarfg, slartg, & slaset, slabad, arscnd, pivout, psvout, psmout c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch, slanhs, slapy2 external pslamch, slanhs, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------------% c unfl = pslamch( comm, 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = pslamch( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call psvout (comm, logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call psvout (comm, logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call psvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call slartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = slapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call slarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call slarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call slarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call slarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call sscal( kplusp-j+1, -one, h(j+1,j), ldh ) call sscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call sscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call sgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %---------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %---------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call saxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call psvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call psmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %----------------% c | End of psnapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psnaup2.f000066400000000000000000000766361260666001200172750ustar00rootroot00000000000000c\BeginDoc c c\Name: psnaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by psnaupd. c c\Usage: c call psnaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in psnaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in psnaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from sneigh. c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c psgetv0 Parallel ARPACK initial vector generation routine. c psnaitr Parallel ARPACK Arnoldi factorization routine. c psnapps Parallel ARPACK application of implicit shifts routine. c snconv ARPACK convergence of Ritz values routine. c psneigh Parallel ARPACK compute Ritz values and error bounds routine. c psngets Parallel ARPACK reorder Ritz values and error bounds routine. c ssortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psmout Parallel ARPACK utility routine that prints matrices c psvout ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Revision history: c Starting Point: Serial Code FILE: naup2.F SID: 2.2 c c\SCCS Information: c FILE: naup2.F SID: 1.5 DATE OF SID: 06/01/00 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Real & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv, & j Real & rnorm , temp , eps23 save cnorm , getv0, initv , update, ushift, & rnorm , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , eps23 , numcnv c Real & rnorm_buf c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, psgetv0, psnaitr, snconv, & psneigh, psngets, psnapps, & psvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, slapy2, pslamch external sdot, psnorm2, slapy2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call psgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call psnaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine psnapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call psnaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call psneigh ( comm, rnorm, kplusp, h, ldh, ritzr, ritzi, & bounds, q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from psneigh. | c %----------------------------------------------------% c call scopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1) call scopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of psngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call psngets ( comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call snconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call pivout (comm, logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call psvout (comm, logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call psvout (comm, logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call svout(logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with sngets, we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in sngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call ssortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call ssortc(wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call ssortc(wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call ssortc(which, .true., nconv, ritzr, ritzi, bounds) c c if (msglvl .gt. 1) then call svout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call svout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call svout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call psngets(comm, ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call psvout (comm, logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call psvout (comm, logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call psvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call scopy (np, workl, 1, ritzr, 1) call scopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call psvout (comm, logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call psvout (comm, logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call psvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call psnapps (comm, n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to psnaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) endif c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if cnorm = .false. c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call psmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of psnaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/psnaupd.f000066400000000000000000000727651260666001200173560ustar00rootroot00000000000000c\BeginDoc c c\Name: psnaupd c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine ssaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c psnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call psnaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to psnaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c psnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Real array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of psnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), psnaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by sneupd. See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c psneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine sneupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine sneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call sneupd immediately following c completion of psnaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Real resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Real resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c psnaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.9 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine psnaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external psnaup2, psvout, pivout, arscnd, sstatn c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pslamch(comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine psneigh called | c | by psnaup2. Subroutine sneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call psnaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within psnaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call psvout (comm, logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call psvout (comm, logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call psvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of psnaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psneigh.f000066400000000000000000000247441260666001200173330ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psneigh c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call psneigh c ( COMM, RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Real N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Real N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from slahqr or strevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c slahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c slacpy LAPACK matrix copy routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another . c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq Cray Research, Inc. & c Dept. of Computational & CRPC / Rice University c Applied Mathematics Houston, Texas c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neigh.F SID: 2.2 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine psneigh ( comm, rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Real & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, slacpy, slahqr, strevc, svout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2 external slapy2, snrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call psmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | slahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call slacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = one call slahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call psvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call strevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = snrm2( n, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2( snrm2( n, q(1,i), 1 ), & snrm2( n, q(1,i+1), 1 ) ) call sscal ( n, one / temp, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call sgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * slapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call psvout (comm, logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call psvout (comm, logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call psvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of psneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psneupd.f000066400000000000000000001264031260666001200173470ustar00rootroot00000000000000c\BeginDoc c c\Name: psneupd c c Message Passing Layer: MPI c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PSNAUPD. PSNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine PSNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of PSNAUPD. c c\Usage: c call psneupd c ( COMM, RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, c WORKEV, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Real array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c PSNAUPD. A further computation must be performed by the user c to transform the Ritz values computed for OP by PSNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Real array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Real N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PSNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Real (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Real (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Real work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PSNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSNEUPD following the last call c to PSNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSNAUPD and the call to PSNEUPD. c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Real N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PSNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c PSNAUPD. They are not changed by PSNEUPD. c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointers into WORKL for addresses c of the above information computed by PSNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PSNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine slahqr c could not be reordered by LAPACK routine strsen. c Re-enter subroutine psneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine slahqr. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine strevc. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PSNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: PSNEUPD got a different count of the number of converged c Ritz values than PSNAUPD got. This indicates the user c probably made an error in passing data from PSNAUPD to c PSNEUPD or that the data was modified before entering c PSNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c psmout Parallel ARPACK utility routine that prints matrices c psvout Parallel ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c slahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c pslamch ScaLAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK matrix initialization routine. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c strsen LAPACK routine that re-orders the Schur form. c strmm Level 3 BLAS matrix times an upper triangular matrix. c sger Level 2 BLAS rank one update to a matrix. c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let X` denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the real c upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by PSNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c Z(:,I)` * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c Z(:,I)` * A * Z(:,I) + Z(:,I+1)` * A * Z(:,I+1), c Z(:,I)` * A * Z(:,I+1) - Z(:,I+1)` * A * Z(:,I), respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute V(:,1:IPARAM(5))` * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: neupd.F SID: 2.3 c c\SCCS Information: c FILE: neupd.F SID: 1.8 DATE OF SID: 04/10/01 c c\EndLib c c----------------------------------------------------------------------- subroutine psneupd & (comm , rvec , howmny, select, dr , di , & z , ldz , sigmar, sigmai, workev, bmat, & n , which, nev , tol , resid , & ncv , v , ldv , iparam, ipntr , & workd, workl, lworkl, info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & dr(nev+1) , di(nev+1) , resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr, ih, ihbds, & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj logical reord Real & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, & slahqr, slaset, psmout, sorm2r, & strevc, strmm , strsen, sscal , & psvout, pivout c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2, pslamch external slapy2, snrm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by PSNEUPD. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call psvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call psvout (comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call psngets(comm , ishift , which , & nev , np , workl(irr), & workl(iri), workl(bounds), & workl , workl(np+1)) c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call psvout (comm, logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call psvout (comm, logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & slapy2 ( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine slahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by PSNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call slaset('All', ncv, ncv, zero, one, workl(invsub), ldq) call slahqr(.true. , .true. , ncv, 1 , & ncv , workl(iuptri), ldh, workl(iheigr), & workl(iheigi), 1 , ncv, workl(invsub), & ldq , ierr) call scopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call psvout (comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call psvout (comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call psvout (comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call psmout (comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call strsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheigr), & workl(iheigi), nconv , conds , & sep , workl(ihbds) , ncv , & iwork , 1 , ierr ) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call psvout(comm, logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call psmout(comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call scopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using sorm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call slacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call sscal(nconv, -one, workl(iuptri+j-1), ldq) call sscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call strevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = snrm2( ncv, workl(invsub+(j-1)*ldq), 1 ) call sscal ( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2(snrm2(ncv, & workl(invsub+(j-1)*ldq), & 1 ), & snrm2(ncv, & workl(invsub+j*ldq), & 1) & ) call sscal(ncv, one/temp, & workl(invsub+(j-1)*ldq), 1) call sscal(ncv, one/temp, & workl(invsub+j*ldq), 1) iconj = 1 else iconj = 0 end if c end if c 40 continue c call sgemv('T' , ncv , nconv, & one , workl(invsub), ldq , & workl(ihbds), 1 , zero , & workev , 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = slapy2(workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call psmout(comm, logfil, ncv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call scopy(nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call strmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PSNAUPD into DR and DI | c %------------------------------------------------------% c call scopy(nconv, workl(ritzr), 1, dr, 1) call scopy(nconv, workl(ritzi), 1, di, 1) call scopy(nconv, workl(ritzr), 1, workl(iheigr), 1) call scopy(nconv, workl(ritzi), 1, workl(iheigi), 1) call scopy(nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) do 50 k=1, ncv temp = slapy2(workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = slapy2(workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1) / temp / temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1) / temp / temp & + sigmai 80 continue c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call psvout (comm, logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call psvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call psvout (comm, logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call psvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheigr+j-1) else if (iconj .eq. 0) then temp = slapy2( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call sger(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of PSNEUPD | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psngets.f000066400000000000000000000202041260666001200173440ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psngets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call psngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Real array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortc ARPACK sorting routine. c scopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: ngets.F SID: 2.2 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine psngets & ( comm, ishift, which, kev, np, ritzr, ritzi, & bounds, shiftr, shifti ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, ssortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call ssortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call ssortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call ssortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine psnapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call ssortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call psvout (comm, logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call psvout (comm, logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call psvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of psngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psnorm2.f000066400000000000000000000034231260666001200172650ustar00rootroot00000000000000c\BeginDoc c c\Name: psnorm2 c c Message Passing Layer: MPI c c\Description: c c\Usage: c call psnorm2 ( COMM, N, X, INC ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c\SCCS Information: c FILE: norm2.F SID: 1.2 DATE OF SID: 2/22/96 c c----------------------------------------------------------------------- c Real function psnorm2 ( comm, n, x, inc ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm, ierr c c %------------------% c | Scalar Arguments | c %------------------% c integer n, inc c c %-----------------% c | Array Arguments | c %-----------------% c Real & x(n) c c %---------------% c | Local Scalars | c %---------------% c Real & max, buf, zero parameter ( zero = 0.0 ) c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %--------------------% c | External Functions | c %--------------------% c Real & snrm2 External snrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c psnorm2 = snrm2( n, x, inc) c buf = psnorm2 call MPI_ALLREDUCE( buf, max, 1, MPI_REAL, & MPI_MAX, comm, ierr ) if ( max .eq. zero ) then psnorm2 = zero else buf = (psnorm2/max)**2.0 call MPI_ALLREDUCE( buf, psnorm2, 1, MPI_REAL, & MPI_SUM, comm, ierr ) psnorm2 = max * sqrt(abs(psnorm2)) endif c c %----------------% c | End of psnorm2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pssaitr.f000066400000000000000000000766051260666001200173660ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pssaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pssaitr c ( COMM, IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See pssaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c WORKL Real work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c psgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c psmout Parallel ARPACK utility routine that prints matrices. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saitr.F SID: 2.3 c c\SCCS Information: c FILE: saitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pssaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaitr & (comm, ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, infol, & jj Real & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c Real & rnorm_buf c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, psgetv0, psvout, psmout, & slascl, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, pslamch external sdot, psnorm2, pslamch c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = pslamch(comm,'safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | psgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call psvout (comm, logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call psgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c rnorm_buf = sdot (n, resid, 1, workd(ivj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, wnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call sgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_REAL, MPI_SUM, comm, ierr) else if (mode .eq. 2) then call sgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_REAL, MPI_SUM, comm, ierr) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv('N', n, j, -one, v, ldv, workl(1), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workl(j) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_REAL, MPI_SUM, comm, ierr) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workl(j) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( rnorm_buf, rnorm1, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = psnorm2( comm, n, resid, 1 ) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call psvout (comm, logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call sscal(n, -one, v(1,j+1), 1) else call sscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call psvout (comm, logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call psvout (comm, logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pssaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pssapps.f000066400000000000000000000444541260666001200173670ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pssapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Real array of length NP. (INPUT) c The shifts to be applied. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c slartg LAPACK Givens rotation construction routine. c slacpy LAPACK matrix copy routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sapps.F SID: 2.4 c c\SCCS Information: c FILE: sapps.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine pssapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Real & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slartg, slaset, psvout, & pivout, arscnd, sgemv c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = pslamch(comm, 'Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call psvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call sscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call psvout (comm, logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call sgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call saxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call psvout (comm, logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call psvout (comm, logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call psvout (comm, logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %----------------% c | End of pssapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pssaup2.f000066400000000000000000001007021260666001200172600ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by pssaupd. c c\Usage: c call pssaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pssaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pssaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the second column c of H starting at H(1,2). If pssaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Real array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in pssaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c psgetv0 Parallel ARPACK initial vector generation routine. c pssaitr Parallel ARPACK Lanczos factorization routine. c pssapps Parallel ARPACK application of implicit shifts routine. c ssconv ARPACK convergence of Ritz values routine. c psseigt Parallel ARPACK compute Ritz values and error bounds routine. c pssgets Parallel ARPACK reorder Ritz values and error bounds routine. c ssortr ARPACK sorting routine. c sstrqb ARPACK routine that computes all eigenvalues and the c last component of the eigenvectors of a symmetric c tridiagonal matrix using the implicit QL or QR method. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c psnorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saup2.F SID: 2.4 c c\SCCS Information: c FILE: saup2.F SID: 1.5 DATE OF SID: 05/20/98 c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Real & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c Real & rnorm_buf c c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, psgetv0, pssaitr, sscal, ssconv, & psseigt, pssgets, pssapps, & ssortr, psvout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, psnorm2, pslamch external sdot, psnorm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0/3.0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %---------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %---------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call psgetv0 ( comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call pssaitr (comm, ido, bmat, n, 0, nev0, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pssaitr was unable to build an Lanczos factorization| c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call pivout (comm, logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call pssaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, h, ldh, ipntr, & workd, workl, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | pssaitr was unable to build an Lanczos factorization| c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call psseigt ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call scopy(kplusp, ritz, 1, workl(kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call pssgets ( comm, ishift, which, nev, np, ritz, & bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(np+1), 1) call ssconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call psvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call ssortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then call sswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call sswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call ssortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call ssortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call psvout (comm, logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call psvout (comm, logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pssgets ( comm, ishift, which, nev, np, & ritz, bounds, workl) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_saup2: NEV and NP .') call psvout (comm, logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call psvout (comm, logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, pssgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call scopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call psvout (comm, logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call psvout (comm, logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After pssapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call pssapps ( comm, n, nev, np, ritz, v, ldv, h, ldh, resid, & q, ldq, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pssaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm_buf = sdot (n, resid, 1, workd, 1) call MPI_ALLREDUCE( rnorm_buf, rnorm, 1, & MPI_REAL, MPI_SUM, comm, ierr ) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = psnorm2( comm, n, resid, 1 ) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call psvout (comm, logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call psvout (comm, logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call psvout (comm, logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %----------------% c | End of pssaup2 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pssaupd.f000066400000000000000000000713431260666001200173520ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssaupd c c Message Passing Layer: MPI c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pssaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pssaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pssaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pssaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Real N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of pssaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), pssaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by psseupd. See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c psseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine psseupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine psseupd. c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call psseupd immediately following completion c of pssaupd. This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c pssaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c sstats ARPACK routine that initializes timing and other statistics c variables. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c pslamch ScaLAPACK routine that determines machine constants. c c\Authors c Kristi Maschhoff ( Parallel Code ) c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: saupd.F SID: 2.4 c c\SCCS Information: c FILE: saupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pssaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0 , zero = 0.0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pssaup2, psvout, pivout, arscnd, sstats c c %--------------------% c | External Functions | c %--------------------% c Real & pslamch external pslamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = pslamch(comm, 'EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call pssaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pssaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call psvout (comm, logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call psvout (comm, logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.1' , 19x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if end if c 9000 continue c return c c %----------------% c | End of pssaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psseigt.f000066400000000000000000000127251260666001200173500ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: psseigt c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call psseigt c ( COMM, RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Real scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Real N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Real array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Real work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from sstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c sstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seigt.F SID: 2.2 c c\SCCS Information: c FILE: seigt.F SID: 1.3 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine psseigt & ( comm, rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, sstqrb, psvout, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call psvout (comm, logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call psvout (comm, logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c c call scopy (n, h(1,2), 1, eig, 1) call scopy (n-1, h(2,1), 1, workl, 1) call sstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call psvout (comm, logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %-----------------% c | End of psseigt | c %-----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/psseupd.f000066400000000000000000001034171260666001200173540ustar00rootroot00000000000000c\BeginDoc c c\Name: psseupd c c Message Passing Layer: MPI c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by PSSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in PSSAUPD documentation.) PSSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine PSSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call psseupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as workspace. c c D Real array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by pssaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by PSSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Real (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to PSNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to PSSEUPD following the last call c to PSSAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PSSAUPD and the call to PSSEUPD. c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c PSSAUPD. They are not changed by PSSEUPD. c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointers into WORKL for addresses c of the above information computed by PSSEUPD. c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c PSSEUPD if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: PSSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: SSEUPD got a different count of the number of converged c Ritz values than SSAUPD got. This indicates the user c probably made an error in passing data from SSAUPD to c SSEUPD or that the data was modified before entering c SSEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c ssesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c ssortr ssortr ARPACK sorting routine. c psnorm2 Parallel ARPACK routine that computes the 2-norm of a vector. c pivout Parallel ARPACK utility routine that prints integers. c psvout Parallel ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c pslamch ScaLAPACK routine that determines machine constants. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c ssteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c sger Level 2 BLAS rank one update to a matrix. c scopy Level 1 BLAS that copies one vector to another . c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: seupd.F SID: 2.4 c c\SCCS Information: c FILE: seupd.F SID: 1.11 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine psseupd & (comm , rvec , howmny, select, d , & z , ldz , sigma , bmat , n , & which , nev , tol , resid , ncv , & v , ldv , iparam, ipntr , workd, & workl , lworkl, info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Real & d(nev), resid(n), v(ldv,ncv), z(ldz, nev), & workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Real & bnorm2, rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, sorm2r, sscal, & ssesrt, ssteqr, sswap , psvout, pivout, ssortr c c %--------------------% c | External Functions | c %--------------------% c Real & psnorm2, pslamch external psnorm2, pslamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | pssaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by pssaupd and is not | c | modified by psseupd. | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by psseupd. | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | ssteqr. Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by ssteqr and by psseupd. | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = pslamch(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of pssaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = psnorm2(comm, n, workd, 1) end if c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call psvout(comm, logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irz). Move | c | the corresponding error estimates | c | in workl(bound) accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pssgets(comm , ishift, which , & nev , np , workl(irz), & workl(bounds), workl) c if (msglvl .gt. 2) then call psvout(comm, logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call psvout(comm, logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy (ncv-1, workl(ih+1) , 1, workl(ihb), 1) call scopy (ncv , workl(ih+ldh), 1, workl(ihd), 1) c call ssteqr('Identity', ncv , workl(ihd), & workl(ihb), workl(iq), ldq , & workl(iw) , ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call scopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call psvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call psvout (comm, logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if (.not.select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call scopy(ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call scopy(ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call scopy(ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c 30 end if c if (msglvl .gt. 2) then call psvout (comm, logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call scopy(nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call scopy(nconv, workl(ritz), 1, d, 1) call scopy(ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by pssaupd. | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call scopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call scopy (nconv, workl(ihd), 1, d, 1) call ssortr('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) call sscal(ncv, bnorm2/rnorm, workl(ihb), 1) call ssortr('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call sorm2r('Right' , 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr ) call slacpy('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call sorm2r('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr ) c else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by pssaupd. | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call sscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / ( workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call psvout (comm, logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call psvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call psvout (comm, logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call psvout (comm, logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iq+k*ldq+ncv-1) & / (workl(iw+k)-one) 120 continue c end if c if (type .ne. 'REGULR') & call sger(n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %----------------% c | End of psseupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pssgets.f000066400000000000000000000170621260666001200173610ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: pssgets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pssgets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Real array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Real array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortr ARPACK utility sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c psvout Parallel ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c sswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Code FILE: sgets.F SID: 2.3 c c\SCCS Information: c FILE: sgets.F SID: 1.2 DATE OF SID: 2/22/96 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pssgets & ( comm, ishift, which, kev, np, ritz, bounds, shifts ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external sswap, scopy, ssortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call ssortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call sswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call sswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call ssortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pssapps. | c %-------------------------------------------------------% c call ssortr ('SM', .true., np, bounds, ritz) call scopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_sgets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_sgets: NP is') call psvout (comm, logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call psvout (comm, logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %----------------% c | End of pssgets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pzgetv0.f000066400000000000000000000344601260666001200172710ustar00rootroot00000000000000c\BeginDoc c c\Name: pzgetv0 c c Message Passing Layer: MPI c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call pzgetv0 c ( COMM, IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, WORKL, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pzgetv0 . c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that pzgetv0 is called. c It should be set to 1 on the initial call to pzgetv0 . c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex*16 N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex*16 work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c WORKL Complex*16 work space used for Gram Schmidt orthogonalization c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c pzvout Parallel ARPACK utility routine that prints vectors. c pzlarnv Parallel wrapper for LAPACK routine zlarnv (generates a random vector). c zgemv Level 2 BLAS routine for matrix vector multiplication. c zcopy Level 1 BLAS that copies one vector to another. c zdotc Level 1 BLAS that computes the scalar product of two vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: getv0.F SID: 2.1 c c\SCCS Information: c FILE: getv0.F SID: 1.7 DATE OF SID: 04/12/01 c c\EndLib c c----------------------------------------------------------------------- c subroutine pzgetv0 & ( comm, ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, workl, ierr ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & resid(n), v(ldv,j), workd(2*n), workl(2*j) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) , & rzero = 0.0 ) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj, myid, igen Double precision & rnorm0 Complex*16 & cnorm, cnorm2 save first, iseed, inits, iter, msglvl, orth, rnorm0 c Complex*16 & cnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy , zgemv , pzlarnv , pzvout , arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdznorm2 , dlapy2 Complex*16 & zdotc external zdotc , pdznorm2 , dlapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then c c %-----------------------------------% c | Generate a seed on each processor | c | using process id (myid). | c | Note: the seed must be between 1 | c | and 4095. iseed(4) must be odd. | c %-----------------------------------% c call MPI_COMM_RANK(comm, myid, ierr) igen = 1000 + 2*myid + 1 if (igen .gt. 4095) then write(0,*) 'Error in p_getv0: seed exceeds 4095!' end if c iseed(1) = igen/1000 igen = mod(igen,1000) iseed(2) = igen/100 igen = mod(igen,100) iseed(3) = igen/10 iseed(4) = mod(igen,10) c inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call pzlarnv (comm, idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call zcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm_buf = zdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_DOUBLE_COMPLEX , MPI_SUM, comm, ierr ) rnorm0 = sqrt(dlapy2 (dble (cnorm),dimag (cnorm))) else if (bmat .eq. 'I') then rnorm0 = pdznorm2 ( comm, n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett`s book, page 107 and in Gragg and Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call zgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl, j-1, & MPI_DOUBLE_COMPLEX , MPI_SUM, comm, ierr) call zgemv ('N', n, j-1, -one, v, ldv, workl, 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm_buf = zdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_DOUBLE_COMPLEX , MPI_SUM, comm, ierr ) rnorm = sqrt(dlapy2 (dble (cnorm),dimag (cnorm))) else if (bmat .eq. 'I') then rnorm = pdznorm2 (comm, n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call pdvout (comm, logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5 ) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then cnorm2 = dcmplx (rnorm,rzero) call pzvout (comm, logfil, 1, cnorm2, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call pzvout (comm, logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %----------------% c | End of pzgetv0 | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pzlarnv.f000066400000000000000000000036341260666001200173650ustar00rootroot00000000000000c\BeginDoc c c\Name: pzlarnv c c Message Passing Layer: MPI c c\Description: c c Parallel Version of ARPACK utility routine zlarnv c c PZLARNV returns a vector of n (nloc) random Complex*16 numbers from a uniform or c normal distribution. It is assumed that X is distributed across a 1-D array c of processors ( nprocs < 1000 ) c c\Arguments c COMM MPI Communicator for the processor grid c c IDIST (input) INTEGER c Specifies the distribution of the random numbers: c = 1: uniform (0,1) c = 2: uniform (-1,1) c = 3: normal (0,1) c c ISEED (input/output) INTEGER array, dimension (4) c On entry, the seed of the random number generator; the array c elements must be between 0 and 4095, and ISEED(4) must be c odd. c On exit, the seed is updated. c c N (input) INTEGER c The number of random numbers to be generated. c c X (output) Complex*16 array, dimension (N) c The generated random numbers. c c\Author: Kristi Maschhoff c c\Details c c Simple parallel version of LAPACK auxiliary routine zlarnv c for X distributed across a 1-D array of processors. c This routine calls the auxiliary routine CLARNV to generate random c Complex*16 numbers from a uniform or normal distribution. Output is consistent c with serial version. c c\SCCS Information: c FILE: larnv.F SID: 1.3 DATE OF SID: 04/17/99 c c----------------------------------------------------------------------- c subroutine pzlarnv( comm, idist, iseed, n, x ) c integer comm c .. c .. Scalar Arguments .. integer idist, n c .. c .. Array Arguments .. integer iseed( 4 ) Complex*16 & x( * ) c .. c .. External Subroutines .. external zlarnv c .. c .. Executable Statements .. c call zlarnv ( idist, iseed, n, x ) c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pznaitr.f000066400000000000000000000772361260666001200173710ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaitr c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in pznaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call pznaitr c ( COMM, IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, WORKL, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See pznaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex*16 N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c WORKL Complex*16 work space used for Gram Schmidt orthogonalization c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pzgetv0 Parallel ARPACK routine to generate the initial vector. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zlanhs LAPACK routine that computes various norms of a matrix. c zlascl LAPACK routine for careful scaling of a matrix. c dlabad LAPACK routine for defining the underflow and overflow c limits c pdlamch10 ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of c two vectors. c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c pdznorm2 Parallel version of Level 1 BLAS that computes the c norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Code FILE: naitr.F SID: 2.1 c c\SCCS Information: c FILE: naitr.F SID: 1.3 DATE OF SID: 3/19/97 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in pznaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaitr & (comm, ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, workl, info) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n), & workl(2*ldh) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone, rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0, rzero = 0.0) c c %--------------% c | Local Arrays | c %--------------% c Double precision & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex*16 & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c Complex*16 & cnorm_buf c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zscal, zgemv, pzgetv0, dlabad, & zdscal, pzvout, pzmout, pivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex*16 & zdotc Double precision & pdlamch10, pdznorm2, zlanhs, dlapy2 external zdotc, pdznorm2, zlanhs, pdlamch10, dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag, dble, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------% c unfl = pdlamch10(comm, 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = pdlamch10( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | pzgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call pzvout (comm, logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call pzgetv0 (comm, ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, workl, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call zcopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call zdscal (n, temp1, v(1,j), 1) call zdscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine zlascl | c %-----------------------------------------% c call zlascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call zlascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call zcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call zcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm_buf = zdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr ) wnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = pdznorm2(comm, n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl, 1) call MPI_ALLREDUCE( workl, h(1,j), j, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = dcmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm_buf = zdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr ) rnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = pdznorm2(comm, n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call pdvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call pzvout (comm, logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workl(j+1), 1) call MPI_ALLREDUCE( workl(j+1), workl(1), j, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, workl(1), 1, & one, resid, 1) call zaxpy (j, one, workl(1), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm_buf = zdotc (n, resid, 1, workd(ipj), 1) call MPI_ALLREDUCE( cnorm_buf, cnorm, 1, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr ) rnorm1 = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = pdznorm2(comm, n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call pivout (comm, logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call pdvout (comm, logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %--------------------------------------------% c tst1 = dlapy2(dble(h(i,i)),dimag(h(i,i))) & + dlapy2(dble(h(i+1,i+1)), dimag(h(i+1,i+1))) if( tst1.eq.dble(zero) ) & tst1 = zlanhs( '1', k+np, h, ldh, workd(n+1) ) if( dlapy2(dble(h(i+1,i)),dimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call pzmout (comm, logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %----------------% c | End of pznaitr | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pznapps.f000066400000000000000000000432521260666001200173640ustar00rootroot00000000000000c\BeginDoc c c\Name: pznapps c c Message Passing Layer: MPI c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call pznapps c ( COMM, N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex*16 array of length NP. (INPUT) c The shifts to be applied. c c V Complex*16 N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex*16 KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex*16 work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlanhs LAPACK routine that computes various norms of a matrix. c zlartg LAPACK Givens rotation construction routine. c zlaset LAPACK matrix initialization routine. c dlabad LAPACK routine for defining the underflow and overflow c limits. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another. c zscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: napps.F SID: 2.1 c c\SCCS Information: c FILE: napps.F SID: 1.4 DATE OF SID: 10/25/03 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine zlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine pznapps & ( comm, n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex*16 & cdum, f, g, h11, h21, r, s, sigma, t Double precision & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zgemv, zscal, zlacpy, zlartg, & pzvout, zlaset, dlabad, pzmout, arscnd, pivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & zlanhs, pdlamch10, dlapy2 external zlanhs, pdlamch10, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, dimag, conjg, dcmplx, max, min, dble c c %---------------------% c | Statement Functions | c %---------------------% c Double precision & cabs1 cabs1( cdum ) = abs( dble( cdum ) ) + abs( dimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------------% c unfl = pdlamch10( comm, 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = pdlamch10( comm, 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call zlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call pivout (comm, logfil, 1, jj, ndigit, & '_napps: shift number.') call pzvout (comm, logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %----------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = zlanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(dble(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call pivout (comm, logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call pivout (comm, logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call pzvout (comm, logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, istart, ndigit, & '_napps: Start of current block ') call pivout (comm, logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call zlartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( dble( h(j+1,j) ) .lt. rzero .or. & dimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / dlapy2(dble(h(j+1,j)),dimag(h(j+1,j))) call zscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call zscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call zscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = dcmplx( dble( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = zlanhs( '1', kev, h, ldh, workl ) if( dble( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call zgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call zcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call zlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call zscal (n, q(kplusp,kev), resid, 1) if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zaxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call pzvout (comm, logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call pzvout (comm, logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call pivout (comm, logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call pzmout (comm, logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %----------------% c | End of pznapps | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pznaup2.f000066400000000000000000000725221260666001200172720ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaup2 c c Message Passing Layer: MPI c c\Description: c Intermediate level interface called by pznaupd. c c\Usage: c call pznaup2 c ( COMM, IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in pznaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in pznaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex*16 N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex*16 array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex*16 (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in PZNAUPD. c c RWORK Double precision work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c pzgetv0 Parallel ARPACK initial vector generation routine. c pznaitr Parallel ARPACK Arnoldi factorization routine. c pznapps Parallel ARPACK application of implicit shifts routine. c pzneigh Parallel ARPACK compute Ritz values and error bounds routine. c pzngets Parallel ARPACK reorder Ritz values and error bounds routine. c zsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c pdvout ARPACK utility routine that prints vectors. c pdlamch10 ScaLAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of two vectors. c zswap Level 1 BLAS that swaps two vectors. c pdznorm2 Parallel version of Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c FILE: naup2.F SID: 1.7 DATE OF SID: 10/25/03 RELEASE: 1 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaup2 & ( comm, ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c include 'mpif.h' c c %---------------% c | MPI Variables | c %---------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex*16 & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Double precision & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rzero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm, getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex*16 & cmpnorm Double precision & rnorm, eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0, eps23 c Double precision & cmpnorm_buf c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy, pzgetv0, pznaitr, pzneigh, pzngets, pznapps, & zsortc, zswap, pzmout, pzvout, pivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex*16 & zdotc Double precision & pdznorm2, pdlamch10, dlapy2 external zdotc, pdznorm2, pdlamch10, dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag, dble, min, max, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch10(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call pzgetv0 (comm, ido, bmat, 1, initv, n, 1, v, ldv, & resid, rnorm, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call pznaitr (comm, ido, bmat, n, 0, nev, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine pznapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call pivout (comm, logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call pivout (comm, logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call pznaitr (comm, ido, bmat, n, nev, np, mode, & resid, rnorm, v, ldv, & h, ldh, ipntr, workd, workl, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call pzneigh ( comm, rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from pzneigh. | c %--------------------------------------------------% c call zcopy(kplusp,ritz,1,workl(kplusp**2+1),1) call zcopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call pzngets ( comm, ishift, which, nev, np, ritz, & bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, dlapy2( dble(ritz(np+i)), & dimag(ritz(np+i)) ) ) if ( dlapy2(dble(bounds(np+i)),dimag(bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call pivout (comm, logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call pzvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call pzvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call pzvout(comm, logfil, kplusp, & workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call pzvout(comm, logfil, kplusp, & workl(kplusp**2+kplusp+1), ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to pzneupd if needed | c %------------------------------------------% c h(3,1) = dcmplx(rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call zsortc(wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, dlapy2( dble(ritz(j)), & dimag(ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call zsortc(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, dlapy2( dble(ritz(j)), & dimag(ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call zsortc(which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call pzvout (comm, logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call pzvout (comm, logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call pzngets (comm, ishift, which, nev, np, ritz, & bounds) c end if c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call pivout (comm, logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call pzvout (comm, logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call pzvout (comm, logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call zcopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call pivout (comm, logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call pzvout (comm, logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call pzvout (comm, logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call pznapps(comm, n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to pznaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm_buf = zdotc (n, resid, 1, workd, 1) call MPI_ALLREDUCE( cmpnorm_buf, cmpnorm, 1, & MPI_DOUBLE_COMPLEX, MPI_SUM, comm, ierr ) rnorm = sqrt(dlapy2(dble(cmpnorm),dimag(cmpnorm))) else if (bmat .eq. 'I') then rnorm = pdznorm2(comm, n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call pdvout (comm, logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call pzmout (comm, logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %----------------% c | End of pznaup2 | c %----------------% c return end arpack-ng-3.3.0/PARPACK/SRC/MPI/pznaupd.f000066400000000000000000000674251260666001200173620ustar00rootroot00000000000000c\BeginDoc c c\Name: pznaupd c c Message Passing Layer: MPI c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then dsaupd or dnaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c pznaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call pznaupd c ( COMM, IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to pznaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c pznaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = pdlamch10 (comm, 'EPS') (machine precision as computed c by the ScaLAPACK auxiliary subroutine pdlamch ). c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below) c c V Complex*16 array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of pznaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by pzneupd . See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c zneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex*16 work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Double precision work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine pzneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call pzneupd immediately following c completion of pznaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex*16 resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex*16 resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c pznaup2 Parallel ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c zstatn ARPACK routine that initializes the timing variables. c pivout Parallel ARPACK utility routine that prints integers. c pzvout Parallel ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c pdlamch10 ScaLAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: naupd.F SID: 2.2 c c\SCCS Information: c FILE: naupd.F SID: 1.7 DATE OF SID: 04/10/01 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine pznaupd & ( comm, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, rwork, info ) c include 'mpif.h' c c %------------------% c | MPI Variables | c %------------------% c integer comm, myid c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex*16 & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Double precision & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0) , zero = (0.0, 0.0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external pznaup2 , pzvout , pivout, arscnd, zstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & pdlamch10 external pdlamch10 c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call zstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0 ) tol = pdlamch10 (comm, 'EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine pzneigh called | c | by pznaup2 . Subroutine pzneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call pznaup2 & ( comm, ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within pznaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call pivout (comm, logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call pzvout (comm, logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call pzvout (comm, logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then call MPI_COMM_RANK( comm, myid, ierr ) if ( myid .eq. 0 ) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.1' , 21x, ' =',/ & 5x, '= Version Date: ', ' 3/19/97' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in p_naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if end if c 9000 continue c return c c %----------------% c | End of pznaupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pzneigh.f000066400000000000000000000207061260666001200173340ustar00rootroot00000000000000c\BeginDoc c c\Name: pzneigh c c Message Passing Layer: MPI c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call pzneigh c ( COMM, RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex*16 N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex*16 array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex*16 N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Double precision work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from zlahqr or ztrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c pdvout Parallel ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c zcopy Level 1 BLAS that copies one vector to another. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: neigh.F SID: 2.1 c c\SCCS Information: c FILE: neigh.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine pzneigh (comm, rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Double precision & rwork(n) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone parameter (one = (1.0, 0.0), zero = (0.0, 0.0), & rone = 1.0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex*16 & vl(1) Double precision & temp c c %----------------------% c | External Subroutines | c %----------------------% c external zlacpy, zlahqr, zdscal, ztrevc, zcopy, & pzmout, pzvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2 external dznrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call pzmout (comm, logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | zlahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call zlacpy ('All', n, n, h, ldh, workl, n) call zlaset ('All', n, n, zero, one, q, ldq) call zlahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call zcopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call pzvout (comm, logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ztrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = dznrm2( n, q(1,j), 1 ) call zdscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call zcopy(n, q(n,1), ldq, workl, 1) call pzvout (comm, logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call zcopy(n, q(n,1), n, bounds, 1) call zdscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call pzvout (comm, logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call pzvout (comm, logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %----------------% c | End of pzneigh | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pzneupd.f000066400000000000000000001050101260666001200173450ustar00rootroot00000000000000c\BeginDoc c c\Name: pzneupd c c Message Passing Layer: MPI c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to PZNAUPD. PZNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of PZNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of PZNAUPD. c c\Usage: c call pzneupd c ( COMM, RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex*16 array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex*16 N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by PZNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex*16 (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex*16 work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to PZNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to ZNEUPD following the last call c to PZNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to PZNAUPD and the call to ZNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex*16 N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by PZNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c PZNAUPD. They are not changed by PZNEUPD. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by PZNEUPD. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c PZNEUPD if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ztrsen. c Re-enter subroutine pzneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ztrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: PZNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: ZNEUPD got a different count of the number of converged c Ritz values than ZNAUPD got. This indicates the user c probably made an error in passing data from ZNAUPD to c ZNEUPD or that the data was modified before entering c ZNEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c pivout Parallel ARPACK utility routine that prints integers. c pzmout Parallel ARPACK utility routine that prints matrices c pzvout Parallel ARPACK utility routine that prints vectors. c zgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ztrsen LAPACK routine that re-orders the Schur form. c zunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c pdlamch10 ScaLAPACK routine that determines machine constants. c ztrmm Level 3 BLAS matrix times an upper triangular matrix. c zgeru Level 2 BLAS rank one update to a matrix. c zcopy Level 1 BLAS that copies one vector to another . c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c V(:,1:IPARAM(5))` * V(:,1:IPARAM(5)) = I are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Complex Serial Code FILE: neupd.F SID: 2.2 c c\SCCS Information: c FILE: neupd.F SID: 1.9 DATE OF SID: 10/25/03 c c\EndLib c c----------------------------------------------------------------------- subroutine pzneupd & ( comm , rvec , howmny, select, d , & z , ldz , sigma , workev, bmat , & n , which , nev , tol , resid, & ncv , v , ldv , iparam, ipntr, & workd, workl , lworkl, rwork , info ) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex*16 & sigma Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & rwork(ncv) Complex*16 & d(nev) , resid(n) , v(ldv,ncv) , & z(ldz, nev), workd(3*n), workl(lworkl), & workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift Complex*16 & rnorm, temp, vl(1) Double precision & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy ,zgeru,zgeqr2,zlacpy,pzmout, & zunm2r,ztrmm,pzvout,pivout, & zlahqr c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2,pdlamch10,dlapy2 external dznrm2,pdlamch10,dlapy2 c Complex*16 & zdotc external zdotc c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = pdlamch10(comm, 'Epsilon-Machine') eps23 = eps23**(2.0 / 3.0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by ZNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call pzvout(comm, logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call pzvout(comm, logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call pzngets(comm, ishift, which , & nev , np , workl(irz), & workl(bounds)) c if (msglvl .gt. 2) then call pzvout(comm,logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call pzvout(comm,logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & dlapy2 ( dble (workl(irz+ncv-j)), & dimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & dlapy2( dble (workl(ibd+jj-1)), & dimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nev) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call pivout(comm, logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call pivout(comm, logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine zlahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by PZNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call zcopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call zlaset('All', ncv, ncv, zero, one, workl(invsub), ldq) call zlahqr(.true. , .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr ) call zcopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call pzvout(comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call pzvout(comm, logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call pzmout(comm, logfil, ncv, ncv, & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ztrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv , conds , sep , & workev, ncv, ierr) c if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call pzvout (comm, logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call pzmout (comm, logfil, ncv, ncv, & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call zcopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call zcopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call zgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using zunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call zunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr ) call zlacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( dble( workl(invsub+(j-1)*ldq+j-1) ) .lt. & dble(zero) ) then call zscal(nconv, -one, workl(iuptri+j-1), ldq) call zscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ztrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr ) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = dznrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = dble(one) / rtemp call zdscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = zdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call zcopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call pzvout(comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call pzmout(comm, logfil, nconv, ncv, & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call zcopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ztrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed PZNAUPD into D. | c %--------------------------------------------------% c call zcopy(nconv, workl(ritz), 1, d, 1) call zcopy(nconv, workl(ritz), 1, workl(iheig), 1) call zcopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call pzvout (comm, logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call pzvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call pzvout (comm, logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call pzvout (comm, logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) & / workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call zgeru(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %----------------% c | End of pzneupd | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/pzngets.f000066400000000000000000000135051260666001200173610ustar00rootroot00000000000000c\BeginDoc c c\Name: pzngets c c Message Passing Layer: MPI c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call pzngets c ( COMM, ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c COMM MPI Communicator for the processor grid. (INPUT) c c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c zsortc ARPACK sorting routine. c pivout Parallel ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c pzvout Parallel ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Parallel Modifications c Kristi Maschhoff c c\Revision history: c Starting Point: Serial Complex Code FILE: ngets.F SID: 2.1 c c\SCCS Information: c FILE: ngets.F SID: 1.2 DATE OF SID: 4/19/96 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine pzngets ( comm, ishift, which, kev, np, ritz, bounds) c c %--------------------% c | MPI Communicator | c %--------------------% c integer comm c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0, 0.0), zero = (0.0, 0.0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external pzvout, zsortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call zsortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine pznapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call zsortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call pivout (comm, logfil, 1, kev, ndigit, '_ngets: KEV is') call pivout (comm, logfil, 1, np, ndigit, '_ngets: NP is') call pzvout (comm, logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call pzvout (comm, logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %----------------% c | End of pzngets | c %----------------% c end arpack-ng-3.3.0/PARPACK/SRC/MPI/stat.h000066400000000000000000000017131260666001200166420ustar00rootroot00000000000000c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c c\SCCS Information: @(#) c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2 c real t0, t1, t2, t3, t4, t5 save t0, t1, t2, t3, t4, t5 c integer nopx, nbx, nrorth, nitref, nrstrt real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec common /timing/ & nopx, nbx, nrorth, nitref, nrstrt, & tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec arpack-ng-3.3.0/PARPACK/SRC/Makefile.am000066400000000000000000000000241260666001200171170ustar00rootroot00000000000000SUBDIRS = MPI BLACS arpack-ng-3.3.0/PARPACK/UTIL/000077500000000000000000000000001260666001200152155ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/UTIL/BLACS/000077500000000000000000000000001260666001200160415ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/UTIL/BLACS/Makefile.am000066400000000000000000000003531260666001200200760ustar00rootroot00000000000000SRCS = pivout.f SSRC = psmout.f psvout.f DSRC = pdmout.f pdvout.f CSRC = pcmout.f pcvout.f ZSRC = pzmout.f pzvout.f noinst_LTLIBRARIES = libparpackutilblacs.la libparpackutilblacs_la_SOURCES = $(SRCS) $(SSRC) $(DSRC) $(CSRC) $(ZSRC) arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pcmout.f000066400000000000000000000221011260666001200175130ustar00rootroot00000000000000* * Routine: PCMOUT - Parallel Version of ARPACK utility routine CMOUT * * Purpose: Complex matrix output routine. * * Usage: CALL PCMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: mout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PCMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',E10.3,',',E10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E10.3,',',E10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E12.5,',',E12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E14.7,',',E14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E20.13,',',E20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13, & ') ')) * * * * ENDIF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pcvout.f000066400000000000000000000206111260666001200175300ustar00rootroot00000000000000* Routine: PCVOUT - Parallel Version of ARPACK utility routine CVOUT * * Purpose: Complex vector output routine. * * Usage: CALL PCVOUT (COMM, LOUT, N, CX, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * N - Length of array CX. (Input) * CX - Complex array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: vout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PCVOUT( COMM, LOUT, N, CX, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) * * ENDIF RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',E10.3,',',E10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E10.3,',',E10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E12.5,',',E12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E14.7,',',E14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E20.13,',',E20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pdmout.f000066400000000000000000000140231260666001200175200ustar00rootroot00000000000000* Routine: PDMOUT - Parallel Version of ARPACK utility routine DMOUT * * Purpose: Double precision matrix output routine. * * Usage: CALL PDMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Double precision M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: mout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PDMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LDA, LOUT, M, N * .. * .. Array Arguments .. Double precision & A( LDA, * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, J, K1, K2, LLL, NDIGIT * .. * .. Local Arrays .. CHARACTER ICOL( 3 ) * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Data statements .. DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, FMT = 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10D12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8D14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6D18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5D22.13 ) 9990 FORMAT( 1X, ' ' ) * END IF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pdvout.f000066400000000000000000000107541260666001200175400ustar00rootroot00000000000000* Routine: PDVOUT - Parallel Version of ARPACK utility routine DVOUT * * Purpose: Double precision vector output routine. * * Usage: CALL PDVOUT (COMM, LOUT, N, SX, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * N - Length of array SX. (Input) * SX - Double precision array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: vout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PDVOUT( COMM , LOUT, N, SX, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LOUT, N * .. * .. Array Arguments .. Double precision & SX( * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, K1, K2, LLL, NDIGIT * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, FMT = 9994 ) ENDIF RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10D12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8D14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6D18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5D24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pivout.f000066400000000000000000000077021260666001200175440ustar00rootroot00000000000000* Routine: PIVOUT - Parallel version of ARPACK UTILITY ROUTINE IVOUT * * Purpose: Integer vector output routine. * * Usage: CALL PIVOUT (COMM, LOUT, N, IX, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * N - Length of array IX. (Input) * IX - Integer array to be printed. (Input) * IFMT - Format to be used in printing array IX. (Input) * IDIGIT - Print up to ABS(IDIGIT) decimal digits / number. (Input) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: ivout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PIVOUT (COMM, LOUT, N, IX, IDIGIT, IFMT) * * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER IX(*), N, IDIGIT, LOUT CHARACTER IFMT*(*) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN ( LEN ( IFMT ), 80 ) DO 1 I = 1, LLL LINE(I:I) = '-' 1 CONTINUE * DO 2 I = LLL+1, 80 LINE(I:I) = ' ' 2 CONTINUE * WRITE ( LOUT, 2000 ) IFMT, LINE(1:LLL) 2000 FORMAT ( /1X, A /1X, A ) * IF (N .LE. 0) RETURN NDIGIT = IDIGIT IF (IDIGIT .EQ. 0) NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF (IDIGIT .LT. 0) THEN * NDIGIT = -IDIGIT IF (NDIGIT .LE. 4) THEN DO 10 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 10 CONTINUE * ELSE IF (NDIGIT .LE. 6) THEN DO 30 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 30 CONTINUE * ELSE IF (NDIGIT .LE. 10) THEN DO 50 K1 = 1, N, 5 K2 = MIN0(N,K1+4) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 50 CONTINUE * ELSE DO 70 K1 = 1, N, 3 K2 = MIN0(N,K1+2) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 70 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE * IF (NDIGIT .LE. 4) THEN DO 90 K1 = 1, N, 20 K2 = MIN0(N,K1+19) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 90 CONTINUE * ELSE IF (NDIGIT .LE. 6) THEN DO 110 K1 = 1, N, 15 K2 = MIN0(N,K1+14) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 110 CONTINUE * ELSE IF (NDIGIT .LE. 10) THEN DO 130 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 130 CONTINUE * ELSE DO 150 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 150 CONTINUE END IF END IF WRITE (LOUT,1004) ENDIF * 1000 FORMAT(1X,I4,' - ',I4,':',20(1X,I5)) 1001 FORMAT(1X,I4,' - ',I4,':',15(1X,I7)) 1002 FORMAT(1X,I4,' - ',I4,':',10(1X,I11)) 1003 FORMAT(1X,I4,' - ',I4,':',7(1X,I15)) 1004 FORMAT(1X,' ') * RETURN END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/psmout.f000066400000000000000000000137571260666001200175540ustar00rootroot00000000000000* Routine: PSMOUT - Parallel Version of ARPACK utility routine SMOUT * * Purpose: Real matrix output routine. * * Usage: CALL PSMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Real M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: mout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PSMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LDA, LOUT, M, N * .. * .. Array Arguments .. Real & A( LDA, * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, J, K1, K2, LLL, NDIGIT * .. * .. Local Arrays .. CHARACTER ICOL( 3 ) * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Data statements .. DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, FMT = 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10E12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8E14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6E18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5E22.13 ) 9990 FORMAT( 1X, ' ' ) * END IF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/psvout.f000066400000000000000000000107101260666001200175470ustar00rootroot00000000000000* Routine: PSVOUT - Parallel Version of ARPACK utility routine SVOUT * * Purpose: Real vector output routine. * * Usage: CALL PSVOUT (COMM, LOUT, N, SX, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * N - Length of array SX. (Input) * SX - Real array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: vout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PSVOUT( COMM , LOUT, N, SX, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LOUT, N * .. * .. Array Arguments .. Real & SX( * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, K1, K2, LLL, NDIGIT * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, FMT = 9994 ) ENDIF RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10E12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8E14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6E18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5E24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pzmout.f000066400000000000000000000221121260666001200175440ustar00rootroot00000000000000* * Routine: PZMOUT - Parallel Version of ARPACK utility routine ZMOUT * * Purpose: Complex*16 matrix output routine. * * Usage: CALL PZMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex*16 M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: mout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PZMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex*16 & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',D10.3,',',D10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D10.3,',',D10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D12.5,',',D12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D14.7,',',D14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D20.13,',',D20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13, & ') ')) * * * * ENDIF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/BLACS/pzvout.f000066400000000000000000000206221260666001200175610ustar00rootroot00000000000000* Routine: PZVOUT - Parallel Version of ARPACK utility routine ZVOUT * * Purpose: Complex*16 vector output routine. * * Usage: CALL PZVOUT (COMM, LOUT, N, CX, IDIGIT, IFMT) * * Arguments * COMM - BLACS Communicator for the processor grid * N - Length of array CX. (Input) * CX - Complex*16 array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: vout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PZVOUT( COMM, LOUT, N, CX, IDIGIT, IFMT ) * ... * .. BLACS VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, NPROW, NPCOL, MYPROW, MYPCOL * * .. External Functions .. external BLACS_GRIDINFO * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex*16 & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * * Determine processor configuration * CALL BLACS_GRIDINFO( COMM, NPROW, NPCOL, MYPROW, MYPCOL ) * * .. Only Processor (0,0) will write to file LOUT .. * IF ( (MYPROW .EQ. 0) .AND. (MYPCOL .EQ. 0) ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) * * ENDIF RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',D10.3,',',D10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D10.3,',',D10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D12.5,',',D12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D14.7,',',D14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D20.13,',',D20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/MPI/000077500000000000000000000000001260666001200156425ustar00rootroot00000000000000arpack-ng-3.3.0/PARPACK/UTIL/MPI/Makefile.am000066400000000000000000000003701260666001200176760ustar00rootroot00000000000000F77 = $(MPIF77) SRCS = pivout.f SSRC = psmout.f psvout.f DSRC = pdmout.f pdvout.f CSRC = pcmout.f pcvout.f ZSRC = pzmout.f pzvout.f noinst_LTLIBRARIES = libparpackutilmpi.la libparpackutilmpi_la_SOURCES = $(SRCS) $(SSRC) $(DSRC) $(CSRC) $(ZSRC) arpack-ng-3.3.0/PARPACK/UTIL/MPI/pcmout.f000066400000000000000000000217231260666001200173250ustar00rootroot00000000000000* * Routine: PCMOUT - Parallel Version of ARPACK utility routine CMOUT * * Purpose: Complex matrix output routine. * * Usage: CALL PCMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: mout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PCMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',E10.3,',',E10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E10.3,',',E10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E12.5,',',E12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E14.7,',',E14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E20.13,',',E20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13, & ') ')) * * * * ENDIF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pcvout.f000066400000000000000000000204331260666001200173330ustar00rootroot00000000000000* Routine: PCVOUT - Parallel Version of ARPACK utility routine CVOUT * * Purpose: Complex vector output routine. * * Usage: CALL PCVOUT (COMM, LOUT, N, CX, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * N - Length of array CX. (Input) * CX - Complex array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: vout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PCVOUT( COMM, LOUT, N, CX, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) * * ENDIF RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',E10.3,',',E10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E10.3,',',E10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E12.5,',',E12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E14.7,',',E14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E20.13,',',E20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pdmout.f000066400000000000000000000136451260666001200173320ustar00rootroot00000000000000* Routine: PDMOUT - Parallel Version of ARPACK utility routine DMOUT * * Purpose: Double precision matrix output routine. * * Usage: CALL PDMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Double precision M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: mout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PDMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LDA, LOUT, M, N * .. * .. Array Arguments .. Double precision & A( LDA, * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, J, K1, K2, LLL, NDIGIT * .. * .. Local Arrays .. CHARACTER ICOL( 3 ) * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Data statements .. DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, FMT = 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10D12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8D14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6D18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5D22.13 ) 9990 FORMAT( 1X, ' ' ) * END IF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pdvout.f000066400000000000000000000105761260666001200173430ustar00rootroot00000000000000* Routine: PDVOUT - Parallel Version of ARPACK utility routine DVOUT * * Purpose: Double precision vector output routine. * * Usage: CALL PDVOUT (COMM, LOUT, N, SX, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * N - Length of array SX. (Input) * SX - Double precision array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: vout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PDVOUT( COMM , LOUT, N, SX, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LOUT, N * .. * .. Array Arguments .. Double precision & SX( * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, K1, K2, LLL, NDIGIT * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, FMT = 9994 ) ENDIF RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10D12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8D14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6D18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5D24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pivout.f000066400000000000000000000075261260666001200173510ustar00rootroot00000000000000* Routine: PIVOUT - Parallel version of ARPACK UTILITY ROUTINE IVOUT * * Purpose: Integer vector output routine. * * Usage: CALL PIVOUT (COMM, LOUT, N, IX, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * N - Length of array IX. (Input) * IX - Integer array to be printed. (Input) * IFMT - Format to be used in printing array IX. (Input) * IDIGIT - Print up to ABS(IDIGIT) decimal digits / number. (Input) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: ivout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PIVOUT (COMM, LOUT, N, IX, IDIGIT, IFMT) * include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER IX(*), N, IDIGIT, LOUT CHARACTER IFMT*(*) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN ( LEN ( IFMT ), 80 ) DO 1 I = 1, LLL LINE(I:I) = '-' 1 CONTINUE * DO 2 I = LLL+1, 80 LINE(I:I) = ' ' 2 CONTINUE * WRITE ( LOUT, 2000 ) IFMT, LINE(1:LLL) 2000 FORMAT ( /1X, A /1X, A ) * IF (N .LE. 0) RETURN NDIGIT = IDIGIT IF (IDIGIT .EQ. 0) NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF (IDIGIT .LT. 0) THEN * NDIGIT = -IDIGIT IF (NDIGIT .LE. 4) THEN DO 10 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 10 CONTINUE * ELSE IF (NDIGIT .LE. 6) THEN DO 30 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 30 CONTINUE * ELSE IF (NDIGIT .LE. 10) THEN DO 50 K1 = 1, N, 5 K2 = MIN0(N,K1+4) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 50 CONTINUE * ELSE DO 70 K1 = 1, N, 3 K2 = MIN0(N,K1+2) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 70 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE * IF (NDIGIT .LE. 4) THEN DO 90 K1 = 1, N, 20 K2 = MIN0(N,K1+19) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 90 CONTINUE * ELSE IF (NDIGIT .LE. 6) THEN DO 110 K1 = 1, N, 15 K2 = MIN0(N,K1+14) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 110 CONTINUE * ELSE IF (NDIGIT .LE. 10) THEN DO 130 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 130 CONTINUE * ELSE DO 150 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 150 CONTINUE END IF END IF WRITE (LOUT,1004) ENDIF * 1000 FORMAT(1X,I4,' - ',I4,':',20(1X,I5)) 1001 FORMAT(1X,I4,' - ',I4,':',15(1X,I7)) 1002 FORMAT(1X,I4,' - ',I4,':',10(1X,I11)) 1003 FORMAT(1X,I4,' - ',I4,':',7(1X,I15)) 1004 FORMAT(1X,' ') * RETURN END arpack-ng-3.3.0/PARPACK/UTIL/MPI/psmout.f000066400000000000000000000136011260666001200173410ustar00rootroot00000000000000* Routine: PSMOUT - Parallel Version of ARPACK utility routine SMOUT * * Purpose: Real matrix output routine. * * Usage: CALL PSMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Real M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: mout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PSMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LDA, LOUT, M, N * .. * .. Array Arguments .. Real & A( LDA, * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, J, K1, K2, LLL, NDIGIT * .. * .. Local Arrays .. CHARACTER ICOL( 3 ) * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Data statements .. DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, FMT = 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10E12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8E14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6E18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5E22.13 ) 9990 FORMAT( 1X, ' ' ) * END IF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/MPI/psvout.f000066400000000000000000000105321260666001200173520ustar00rootroot00000000000000* Routine: PSVOUT - Parallel Version of ARPACK utility routine SVOUT * * Purpose: Real vector output routine. * * Usage: CALL PSVOUT (COMM, LOUT, N, SX, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * N - Length of array SX. (Input) * SX - Real array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: * FILE: vout.F SID: 1.2 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PSVOUT( COMM , LOUT, N, SX, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LOUT, N * .. * .. Array Arguments .. Real & SX( * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, K1, K2, LLL, NDIGIT * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, FMT = 9994 ) ENDIF RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10E12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8E14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6E18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5E24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pzmout.f000066400000000000000000000217341260666001200173560ustar00rootroot00000000000000* * Routine: PZMOUT - Parallel Version of ARPACK utility routine ZMOUT * * Purpose: Complex*16 matrix output routine. * * Usage: CALL PZMOUT (COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex*16 M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: mout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PZMOUT( COMM, LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex*16 & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',D10.3,',',D10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D10.3,',',D10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D12.5,',',D12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D14.7,',',D14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D20.13,',',D20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13, & ') ')) * * * * ENDIF RETURN END arpack-ng-3.3.0/PARPACK/UTIL/MPI/pzvout.f000066400000000000000000000204441260666001200173640ustar00rootroot00000000000000* Routine: PZVOUT - Parallel Version of ARPACK utility routine ZVOUT * * Purpose: Complex*16 vector output routine. * * Usage: CALL PZVOUT (COMM, LOUT, N, CX, IDIGIT, IFMT) * * Arguments * COMM - MPI Communicator for the processor grid * N - Length of array CX. (Input) * CX - Complex*16 array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * * FILE: vout.F SID: 1.1 DATE OF SID: 3/19/97 RELEASE: 1 * *----------------------------------------------------------------------- * SUBROUTINE PZVOUT( COMM, LOUT, N, CX, IDIGIT, IFMT ) * ... include 'mpif.h' * * .. MPI VARIABLES AND FUNCTIONS .. * .. Variable Declaration .. integer COMM, MYID, IERR * * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex*16 & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * * Determine processor configuration * call MPI_COMM_RANK( comm, myid, ierr ) * * .. Only Processor 0 will write to file LOUT .. * IF ( MYID .EQ. 0 ) THEN * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) * * ENDIF RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',D10.3,',',D10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D10.3,',',D10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D12.5,',',D12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D14.7,',',D14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D20.13,',',D20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/PARPACK/UTIL/Makefile.am000066400000000000000000000000241260666001200172450ustar00rootroot00000000000000SUBDIRS = MPI BLACS arpack-ng-3.3.0/PARPACK_CHANGES000066400000000000000000000255351260666001200155250ustar00rootroot00000000000000This file describes list of changes done by Chao Yang on parpack. This fixes many issues in parpack libs. Theses changes were released under the "ppatch.tar.gz" filename. --------------------------------------------------------------------- 1. 01/27/97: [s,d]sapps.f: Loop 50 (line 375) has an incorrect upper bound: replace do 50 j = 1, min( j+jj, kplusp ) ^^^ with do 50 j = 1, min( i+jj, kplusp ) ^^^ [s,d]napps.f: Loop 70 (line 433) has an incorrect upper bound: replace do 70 j = 1, min( j+jj, kplusp ) ^^^ with do 70 j = 1, min( i+jj, kplusp ) ^^^ [c,z]napps.f: Loop 70 (line 365) has an incorrect upper bound: replace do 70 j = 1, min( j+jj, kplusp ) ^^^ with do 70 j = 1, min( i+jj, kplusp ) ^^^ Without the change the code will not compile on NEC. The parallel version of these routine needs to be modified as well. 2. 03/28/97: In [s,d]ndrv4.f [s,d]ndrv5.f [s,d]ndrv6.f, the array SELECT is delecared as select(maxnev) It should be changed to select(maxncv) 3. 03/28/97: There are two empty files [s,d]naupe.f in the SRC directory. They are not part of the ARPACK. The user should ignore them. 4. 03/28/97: In [s,d]seupd.f, select(ncv) is declared before ncv is declared. Should move the declaration of select(ncv) after c %-----------------% c | Array Arguments | c %-----------------% 5. 03/28/97: all banded drivers in EXAMPLES/BAND directory have not been checked in. Although these are the current version, the SCCS infomartion do not show the correct version number and dates. 6. 03/28/97: In [s,d]naupd.f the following check: else if (mode .lt. 1 .or. mode .gt. 5) then ^^ ierr = -10 should be changed to else if (mode .lt. 1 .or. mode .gt. 4) then ^^ ierr = -10 In [c,z]naupd.f the following check: else if (mode .lt. 1 .or. mode .gt. 5) then ^^ ierr = -10 should be changed to else if (mode .lt. 1 .or. mode .gt. 3) then ^^ ierr = -10 7. 04/02/97: The mass matrix in the drivers [s,d]ndrv4.f (NONSYM) [s,d]nbdr4.f (BAND) [c,z]ndrv4.f (COMPLEX) [c,z]nbdr4.f (BAND) needs to be scaled by 1/6 to match the piecewise linear finite element discretization of the 1-d convection-diffusion operator as explained in the documentation. 8. 04/03/97: The documentation for the SELECT array in [s,d]seupd.f should say: c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) ^^^^ ^^^^^^^^^^ 9. 06/04/98: p[s,d,c,z]larnv.f The integer arguement IDIST is not declared. 10. 06/04/98: In p[s,d]neupd.f, the declaration of p[s,d]norm2 is missing. The declaration of [s,d]nrm2 is not necessary since it is not used. 11. 08/03/98: In [c,z]nband.f, the documentation: c call znband c ( RVEC, HOWMNY, SELECT, D , Z, LDZ, SIGMA, WORKEV, N, AB, c MB, LDA, FAC, KL, LU, WHICH, BMAT, NEV, TOL, RESID, NCV, ^^^^ c V, LDV, IPARAM, WORKD, WORKL, LWORKL, RWORK, IWORK, INFO ) should read c call znband c ( RVEC, HOWMNY, SELECT, D , Z, LDZ, SIGMA, WORKEV, N, AB, c MB, LDA, FAC, KL, KU, WHICH, BMAT, NEV, TOL, RESID, NCV, ^^^^ c V, LDV, IPARAM, WORKD, WORKL, LWORKL, RWORK, IWORK, INFO ) 12. 03/18/99 _getv0.f failed to generate a starting vector after 2 steps of classical Gram Schmidt correction step. Fixed by increasing the maximum Gram-Schmidt correction steps to 5. 13. 04/16/99 A print statement (*mout) in p*neupd.f went over the 72nd column. 14. 04/17/99 Modified p*larnv.f and p*getv0.f in PARPACK to fix a bug in generating a random starting vector in parallel. Now each processor generates its portion of the starting vector using a different seed. 15. 11/05/99 The do 10 loop in [c,z]neupd.f and p[c,z]neupd.f had incorrect index to workl(irz). Since the loop count j starts from 0, the reference to workl(irz) should be expressed by workl(irz+j) instead of workl(irz+j-1). 16. 06/01/2000 Variables 'rnorm' and 'eps23' are missing from the save statement list in all __naup2 routines (both serial and parallel). 17. 07/20/2000 (all eupd, both serial and parallel) Changed the code segment used to determine whether reordering is necessary to move the desired and converged Ritz values into the leading portion of the Schur form. The previous versions used the technique to mark Ritz values that must be put in the leading portion of the Schur form: 1. Determine which eigenvalues returned by dense eigenvalue calculation routine are desired. This is done in two steps: a) find a threshold value from the sorted Ritz value array b) compare all eigenvalues returned directly from dense eigenvalue calculation routine against this threshold value. 2. For each desired Ritz value, check the Ritz estimate. Mark the j-th element of the select array if the j-th eigenvalue satisfies the convergence criteria. 18. 08/08/2000 In _saitr.f and _naitr.f, add a check for NP = 0 at the very begining of this routine 19. 09/21/2000 In [c,z]neupd.f, the IF statement: if (numcnv .lt. nev .and. ^^^ & slapy2( m_real(workl(ibd+jj-1)), & aimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then is changed to if (numcnv .lt. nconv .and. ^^^^^ & slapy2( m_real(workl(ibd+jj-1)), & aimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then NEV is the number of eigenvalues requested; NCONV is the number of converged eigenvalues; NUMCNV counts the number of converged eigenvalues; The original IF statement will cause NUMCNV to be inconsistent with NCONV, when fewer than NEV wanted eigenvalues have converged but there are many converged but unwanted Ritz values. 20. In [s,d][s,n]eupd.f, the IF statement if (numcnv .lt. nev .and. ^^^ & workl(ibd+jj-1) .le. tol*temp1) then is changed to if (numcnv .lt. nconv .and. ^^^^^ & workl(ibd+jj-1) .le. tol*temp1) then NEV is the number of eigenvalues requested; NCONV is the number of converged eigenvalues; NUMCNV counts the number of converged eigenvalues; The original IF statement will cause NUMCNV to be inconsistent with NCONV, when fewer than NEV wanted eigenvalues have converged but there are many converged but unwanted Ritz values. 21. 10/16/2000 Line 238 of [s,d]naup2.f went past the 72nd column. This was caused by the extra space inserted by new Solaris cpp when ARPACK single and double precision source codes are generate from the naup2.F code. This line is fixed by wrapping it around the next line. 22. 10/20/2000 Updated SCCS information for drivers in BAND, SIMPLE. Fixed miscellaneous minor problems caused by cpp. 23. 04/10/2001 Problems reported in items 19 & 20 above exist in the parallel codes also. The same changes have been made in p[s,d,c,n][s,n]eupd.f 24. 04/10/2001 (reported by David Day, SNL) There was a mistake in the orthogonalization step in the MPI version of p[c,z]getv0.f. The original code had call zgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1, ^^^^^^^^^^ & one, resid, 1) It has been changed to call zgemv ('N', n, j-1, -one, v, ldv, workl, 1, one, resid, 1) ^^^^^ Also, p[c,z]vout() was used to print out `rnorm', which is potential problematic. The following code has been added to correct that. cnorm2 = cmplx(rnorm,rzero) call pcvout (comm, logfil, 1, cnorm2, ndigit, & '_getv0: B-norm of initial / restarted starting vector') 25. 04/10/2001 In all _aupd.f codes, iparam(2) and/or iparam(4) are used to define NB or LEVEC. Since NB=1 is the only block size and since LEVEC is no longer used, the statements levec = iparam(2) nb = iparam(4) have been commented out. NB=1 has been added to avoid potential confusion. 26. 04/10/2001 In all _seupd codes (both serial and parallel) the call to _sgets had an extra arguement: call dsgets (ishift, which , nev , & np , workl(irz) , workl(bounds), & workl , workl(np+1)) ^^^^^^^^^^^ they have been changed to call dsgets (ishift, which , nev , & np , workl(irz) , workl(bounds), & workl) 27. 07/21/2002 In pzneupd.f, loop 11, the intrinsic precision conversion function 'real' should be changed to 'dble' 28. 07/21/2002 modified the comments in [c,z]neupd regarding the size of NCV. NCV is only required to be at least NEV+1 (instead of NEV+2) in the complex version. Changed the error testing from else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 to else if (ncv .le. nev .or. ncv .gt. n) then ierr = -3 29. 07/21/2002 modified the comment in [c,z]naupd regarding the size of NCV. NCV is only required to be at least NEV+1 (instead of NEV+2) in the complex version. 30. 07/21/2002 In [s,d]sbdr2.f, lworkl is incorrectly set to ncv*ncv+6*ncv. Changed it to ncv*ncv+8*ncv. 31. 10/24/2003 There was a typo in p[c,z]neupd. The call to '[c,z]ngets' is replaced by a call to 'p[c,z]ngets' instead. 32. 10/24/2003 fixing lines that go beyond the 72nd column in p[c,z]naup2.f. 33. 10/24/2003 replace 'slamch' with 'pslamch' in p[c,z]napps.f 34. 10/24/2003 removed an extra arguement to the p[s,d]sgets() call. 35. 10/24/2003 p[c,z]naup2.f contain some lines that were incorrectly generated by cpp. These lines have been removed in the new patch. arpack-ng-3.3.0/README000066400000000000000000000065731260666001200142520ustar00rootroot00000000000000ARPACK-NG is a collection of Fortran77 subroutines designed to solve large scale eigenvalue problems. Important Features: * Reverse Communication Interface. * Single and Double Precision Real Arithmetic Versions for Symmetric, Non-symmetric, Standard or Generalized Problems. * Single and Double Precision Complex Arithmetic Versions for Standard or Generalized Problems. * Routines for Banded Matrices - Standard or Generalized Problems. * Routines for The Singular Value Decomposition. * Example driver routines that may be used as templates to implement numerous Shift-Invert strategies for all problem types, data types and precision. This project is a joint project between Debian, Octave and Scilab in order to provide a common and maintained version of arpack. Indeed, no single release has been published by Rice university for the last few years and since many software (Octave, Scilab, R, Matlab...) forked it and implemented their own modifications, arpack-ng aims to tackle this by providing a common repository and maintained versions. arpack-ng is replacing arpack almost everywhere. 1. You have successfully unbundled ARPACK-NG and are now in the ARPACK-NG directory that was created for you. 2. The directory SRC contains the top level routines including the highest level reverse communication interface routines ssaupd, dsaupd - symmetric single and double precision snaupd, dnaupd - non-symmetric single and double precision cnaupd, znaupd - complex non-symmetric single and double precision The headers of these routines contain full documentation of calling sequence and usage. Additional information is in the DOCUMENTS directory. The directory PARPACK contains the Parallel ARPACK routines. 3. Example driver programs that illustrate all the computational modes, data types and precisions may be found in the EXAMPLES directory. Upon executing the 'ls EXAMPLES' command you should see BAND COMPLEX NONSYM README SIMPLE SVD SYM Example programs for banded, complex, nonsymmetric, symmetric, and singular value decomposition may be found in the directories BAND, COMPLEX, NONSYM, SYM, SVD respectively. Look at the README file for further information. To get started, get into the SIMPLE directory to see example programs that illustrate the use of ARPACK in the simplest modes of operation for the most commonly posed standard eigenvalue problems. Example programs for Parallel ARPACK may be found in the directory PARPACK/EXAMPLES. Look at the README file for further information. The following instructions explain how to make the ARPACK library. 4. Unlike ARPACK, ARPACK-NG is providing autotools based build system. Therefor, the classical: $ sh bootstrap $ ./configure $ make $ make install should work as expected. 5. Within DOCUMENTS directory there are three files ex-sym.doc ex-nonsym.doc and ex-complex.doc for templates on how to invoke the computational modes of ARPACK. Also look in the README file for explanations concerning the other documents. Danny Sorensen at sorensen@caam.rice.edu Richard Lehoucq at rblehou@sandia.gov Chao Yang at cyang@lbl.gov Kristi Maschhoff at kristyn@tera.com Sylvestre Ledru at sylvestre@debian.org Allan Cornet at allan.cornet@scilab.org Good luck and enjoy. arpack-ng-3.3.0/SRC/000077500000000000000000000000001260666001200140065ustar00rootroot00000000000000arpack-ng-3.3.0/SRC/Makefile.am000066400000000000000000000014561260666001200160500ustar00rootroot00000000000000SSRC = snaitr.f snapps.f snaup2.f snaupd.f snconv.f sneigh.f sneupd.f sngets.f sstatn.f \ ssaitr.f ssapps.f ssaup2.f ssaupd.f ssconv.f sseigt.f sseupd.f ssgets.f sstats.f \ sgetv0.f ssortc.f ssortr.f ssesrt.f sstqrb.f DSRC = dnaitr.f dnapps.f dnaup2.f dnaupd.f dnconv.f dneigh.f dneupd.f dngets.f dstatn.f \ dsaitr.f dsapps.f dsaup2.f dsaupd.f dsconv.f dseigt.f dseupd.f dsgets.f dstats.f \ dgetv0.f dsortc.f dsortr.f dsesrt.f dstqrb.f CSRC = cnaitr.f cnapps.f cnaup2.f cnaupd.f cneigh.f cneupd.f cngets.f cstatn.f \ cgetv0.f csortc.f ZSRC = znaitr.f znapps.f znaup2.f znaupd.f zneigh.f zneupd.f zngets.f zstatn.f \ zgetv0.f zsortc.f EXTRA_DIST = debug.h stat.h version.h noinst_LTLIBRARIES = libarpacksrc.la libarpacksrc_la_SOURCES = $(SSRC) $(DSRC) $(CSRC) $(ZSRC) arpack-ng-3.3.0/SRC/cgetv0.f000066400000000000000000000311501260666001200153450ustar00rootroot00000000000000c\BeginDoc c c\Name: cgetv0 c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call cgetv0 c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, IERR ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to cgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that cgetv0 is called. c It should be set to 1 on the initial call to cgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c cvout ARPACK utility routine that prints vectors. c clarnv LAPACK routine for generating a random vector. c cgemv Level 2 BLAS routine for matrix vector multiplication. c ccopy Level 1 BLAS that copies one vector to another. c cdotc Level 1 BLAS that computes the scalar product of two vectors. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: getv0.F SID: 2.3 DATE OF SID: 08/27/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine cgetv0 & ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & resid(n), v(ldv,j), workd(2*n) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0), & rzero = 0.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Real & rnorm0 Complex & cnorm save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, cgemv, clarnv, cvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2, slapy2 Complex & cdotc external cdotc, scnrm2, slapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call clarnv (idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call ccopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd, 1) rnorm0 = sqrt(slapy2(real(cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm0 = scnrm2(n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call cgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workd(n+1), 1) call cgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd, 1) rnorm = sqrt(slapy2(real(cnorm),aimag(cnorm))) else if (bmat .eq. 'I') then rnorm = scnrm2(n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call svout (logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call svout (logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call svout (logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call cvout (logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %---------------% c | End of cgetv0 | c %---------------% c end arpack-ng-3.3.0/SRC/cnaitr.f000066400000000000000000000744671260666001200154570ustar00rootroot00000000000000c\BeginDoc c c\Name: cnaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in cnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call cnaitr c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See cnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c cgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c cmout ARPACK utility routine that prints matrices c cvout ARPACK utility routine that prints vectors. c clanhs LAPACK routine that computes various norms of a matrix. c clascl LAPACK routine for careful scaling of a matrix. c slabad LAPACK routine for defining the underflow and overflow c limits. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of two vectors. c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naitr.F SID: 2.3 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in cnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine cnaitr & (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone, rzero parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0), & rone = 1.0E+0, rzero = 0.0E+0) c c %--------------% c | Local Arrays | c %--------------% c Real & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cscal, csscal, cgemv, cgetv0, & slabad, cvout, cmout, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex & cdotc Real & slamch, scnrm2, clanhs, slapy2 external cdotc, scnrm2, clanhs, slamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------% c unfl = slamch( 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = slamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | cgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call ivout (logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call svout (logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call cgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call ccopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call csscal (n, temp1, v(1,j), 1) call csscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine clascl | c %-----------------------------------------% c call clascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call clascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call ccopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call ccopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) wnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = scnrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = cmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) rnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = scnrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call svout (logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call cvout (logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call cgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) call caxpy (j, one, workd(irj), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm = cdotc (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt( slapy2(real(cnorm),aimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = scnrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call ivout (logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call svout (logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %--------------------------------------------% c tst1 = slapy2(real(h(i,i)),aimag(h(i,i))) & + slapy2(real(h(i+1,i+1)), aimag(h(i+1,i+1))) if( tst1.eq.real(zero) ) & tst1 = clanhs( '1', k+np, h, ldh, workd(n+1) ) if( slapy2(real(h(i+1,i)),aimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call cmout (logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of cnaitr | c %---------------% c end arpack-ng-3.3.0/SRC/cnapps.f000066400000000000000000000422061260666001200154450ustar00rootroot00000000000000c\BeginDoc c c\Name: cnapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call cnapps c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex array of length NP. (INPUT) c The shifts to be applied. c c V Complex N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c cmout ARPACK utility routine that prints matrices c cvout ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clanhs LAPACK routine that computes various norms of a matrix. c clartg LAPACK Givens rotation construction routine. c claset LAPACK matrix initialization routine. c slabad LAPACK routine for defining the underflow and overflow c limits. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c cgemv Level 2 BLAS routine for matrix vector multiplication. c caxpy Level 1 BLAS that computes a vector triad. c ccopy Level 1 BLAS that copies one vector to another. c cscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: napps.F SID: 2.3 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine clahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine cnapps & ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0), & rzero = 0.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex & cdum, f, g, h11, h21, r, s, sigma, t Real & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external caxpy, ccopy, cgemv, cscal, clacpy, clartg, & cvout, claset, slabad, cmout, arscnd, ivout c c %--------------------% c | External Functions | c %--------------------% c Real & clanhs, slamch, slapy2 external clanhs, slamch, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, aimag, conjg, cmplx, max, min, real c c %---------------------% c | Statement Functions | c %---------------------% c Real & cabs1 cabs1( cdum ) = abs( real( cdum ) ) + abs( aimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine clahqr | c %-----------------------------------------------% c unfl = slamch( 'safe minimum' ) ovfl = real(one / unfl) call slabad( unfl, ovfl ) ulp = slamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call claset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call ivout (logfil, 1, jj, ndigit, & '_napps: shift number.') call cvout (logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr | c %----------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = clanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(real(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call cvout (logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, istart, ndigit, & '_napps: Start of current block ') call ivout (logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call clartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( real( h(j+1,j) ) .lt. rzero .or. & aimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / slapy2(real(h(j+1,j)),aimag(h(j+1,j))) call cscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call cscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call cscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = cmplx( real( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine clahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = clanhs( '1', kev, h, ldh, workl ) if( real( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call cgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call cgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call ccopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call clacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( real( h(kev+1,kev) ) .gt. rzero ) & call ccopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call cscal (n, q(kplusp,kev), resid, 1) if ( real( h(kev+1,kev) ) .gt. rzero ) & call caxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call cvout (logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call cvout (logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call ivout (logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call cmout (logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %---------------% c | End of cnapps | c %---------------% c end arpack-ng-3.3.0/SRC/cnaup2.f000066400000000000000000000710351260666001200153530ustar00rootroot00000000000000c\BeginDoc c c\Name: cnaup2 c c\Description: c Intermediate level interface called by cnaupd. c c\Usage: c call cnaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in cnaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in cnaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in CNAUPD. c c RWORK Real work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c cgetv0 ARPACK initial vector generation routine. c cnaitr ARPACK Arnoldi factorization routine. c cnapps ARPACK application of implicit shifts routine. c cneigh ARPACK compute Ritz values and error bounds routine. c cngets ARPACK reorder Ritz values and error bounds routine. c csortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c cmout ARPACK utility routine that prints matrices c cvout ARPACK utility routine that prints vectors. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c ccopy Level 1 BLAS that copies one vector to another . c cdotc Level 1 BLAS that computes the scalar product of two vectors. c cswap Level 1 BLAS that swaps two vectors. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice Universitya c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naup2.F SID: 2.6 DATE OF SID: 06/01/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine cnaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Real & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rzero parameter (one = (1.0E+0, 0.0E+0) , zero = (0.0E+0, 0.0E+0) , & rzero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex & cmpnorm Real & rnorm , eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv , & nevbef, nev0 , np0 , eps23 c c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy, cgetv0, cnaitr, cneigh, cngets, cnapps, & csortc, cswap, cmout, cvout, ivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex & cdotc Real & scnrm2, slamch, slapy2 external cdotc, scnrm2, slamch, slapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic aimag, real , min, max c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0 ) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call cgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call cnaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine cnapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call ivout (logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call cnaitr(ido, bmat, n, nev, np, mode, resid, rnorm, & v , ldv , h, ldh, ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call svout (logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call cneigh (rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from cneigh. | c %--------------------------------------------------% c call ccopy(kplusp,ritz,1,workl(kplusp**2+1),1) call ccopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call cngets (ishift, which, nev, np, ritz, bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, slapy2( real (ritz(np+i)), & aimag(ritz(np+i)) ) ) if ( slapy2(real (bounds(np+i)),aimag(bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call ivout (logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call cvout (logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call cvout (logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call cvout(logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call cvout(logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to cneupd if needed | c %------------------------------------------% h(3,1) = cmplx(rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call csortc(wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, slapy2( real (ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call csortc(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, slapy2( real (ritz(j)), & aimag(ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call csortc(which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call cvout (logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call cvout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call cngets (ishift, which, nev, np, ritz, bounds) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call cvout (logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call cvout (logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call ccopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call cvout (logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call cvout (logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call cnapps (n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to cnaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call ccopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call ccopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm = cdotc (n, resid, 1, workd, 1) rnorm = sqrt(slapy2(real (cmpnorm),aimag(cmpnorm))) else if (bmat .eq. 'I') then rnorm = scnrm2(n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call svout (logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call cmout (logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %---------------% c | End of cnaup2 | c %---------------% c return end arpack-ng-3.3.0/SRC/cnaupd.f000066400000000000000000000661771260666001200154500ustar00rootroot00000000000000c\BeginDoc c c\Name: cnaupd c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then ssaupd or snaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c cnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M hermitian positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M hermitian semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call cnaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to cnaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c cnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = slamch('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine slamch). c c RESID Complex array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below.) c c V Complex array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of cnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by cneupd. See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c cneupd if RVEC = .TRUE. See Remark 2 below. c c ------------------------------------------------------------- c c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Real work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine cneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call cneupd immediately following c completion of cnaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requirement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c cnaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c cstatn ARPACK routine that initializes the timing variables. c ivout ARPACK utility routine that prints integers. c cvout ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c slamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine cnaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, rwork, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Real & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0E+0, 0.0E+0) , zero = (0.0E+0, 0.0E+0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external cnaup2, cvout, ivout, arscnd, cstatn c c %--------------------% c | External Functions | c %--------------------% c Real & slamch external slamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call cstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev .or. ncv .gt. n) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0E+0 ) tol = slamch('EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine cneigh called | c | by cnaup2. Subroutine cneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call cnaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within cnaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call cvout (logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call cvout (logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.3' , 21x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if c 9000 continue c return c c %---------------% c | End of cnaupd | c %---------------% c end arpack-ng-3.3.0/SRC/cneigh.f000066400000000000000000000177111260666001200154210ustar00rootroot00000000000000c\BeginDoc c c\Name: cneigh c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call cneigh c ( RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Real work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from clahqr or ctrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c cmout ARPACK utility routine that prints matrices c cvout ARPACK utility routine that prints vectors. c svout ARPACK utility routine that prints vectors. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c ccopy Level 1 BLAS that copies one vector to another. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neigh.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine cneigh (rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Real & rwork(n) c c %------------% c | Parameters | c %------------% c Complex & one, zero Real & rone parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0), & rone = 1.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex & vl(1) Real & temp c c %----------------------% c | External Subroutines | c %----------------------% c external clacpy, clahqr, ctrevc, ccopy, & csscal, cmout, cvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2 external scnrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call cmout (logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | clahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call clacpy ('All', n, n, h, ldh, workl, n) call claset ('All', n, n, zero, one, q, ldq) call clahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call ccopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call cvout (logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ctrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = scnrm2( n, q(1,j), 1 ) call csscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call ccopy(n, q(n,1), ldq, workl, 1) call cvout (logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call ccopy(n, q(n,1), n, bounds, 1) call csscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call cvout (logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call cvout (logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %---------------% c | End of cneigh | c %---------------% c end arpack-ng-3.3.0/SRC/cneupd.f000066400000000000000000001041251260666001200154360ustar00rootroot00000000000000c\BeginDoc c c\Name: cneupd c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to CNAUPD. CNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of CNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of CNAUPD. c c\Usage: c call cneupd c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments: c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by CNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to CNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to CNEUPD following the last call c to CNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to CNAUPD and the call to CNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by CNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c cnaupd. They are not changed by cneupd. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by cneupd. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c cneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ctrsen. c Re-enter subroutine cneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ctrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: CNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: CNEUPD got a different count of the number of converged c Ritz values than CNAUPD got. This indicates the user c probably made an error in passing data from CNAUPD to c CNEUPD or that the data was modified before entering c CNEUPD c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c ivout ARPACK utility routine that prints integers. c cmout ARPACK utility routine that prints matrices c cvout ARPACK utility routine that prints vectors. c cgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c clacpy LAPACK matrix copy routine. c clahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c claset LAPACK matrix initialization routine. c ctrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ctrsen LAPACK routine that re-orders the Schur form. c cunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c slamch LAPACK routine that determines machine constants. c ctrmm Level 3 BLAS matrix times an upper triangular matrix. c cgeru Level 2 BLAS rank one update to a matrix. c ccopy Level 1 BLAS that copies one vector to another . c cscal Level 1 BLAS that scales a vector. c csscal Level 1 BLAS that scales a complex vector by a real number. c scnrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c transpose( V(:,1:IPARAM(5)) ) * V(:,1:IPARAM(5)) = I c are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neupd.F SID: 2.7 DATE OF SID: 09/20/00 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine cneupd(rvec , howmny, select, d , & z , ldz , sigma , workev, & bmat , n , which , nev , & tol , resid , ncv , v , & ldv , iparam, ipntr , workd , & workl, lworkl, rwork , info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex & sigma Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & rwork(ncv) Complex & d(nev) , resid(n) , v(ldv,ncv), & z(ldz, nev), & workd(3*n) , workl(lworkl), workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift, nconv2 Complex & rnorm, temp, vl(1) Real & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external ccopy , cgeru, cgeqr2, clacpy, cmout, & cunm2r, ctrmm, cvout, ivout, & clahqr c c %--------------------% c | External Functions | c %--------------------% c Real & scnrm2, slamch, slapy2 external scnrm2, slamch, slapy2 c Complex & cdotc external cdotc c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by CNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call cvout(logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call cvout(logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call cngets(ishift, which , nev , & np , workl(irz), workl(bounds)) c if (msglvl .gt. 2) then call cvout (logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call cvout (logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & slapy2 ( real(workl(irz+ncv-j)), & aimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & slapy2( real(workl(ibd+jj-1)), & aimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine clahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by CNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call ccopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call claset('All', ncv, ncv , & zero , one, workl(invsub), & ldq) call clahqr(.true., .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr) call ccopy(ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call cvout (logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call cvout (logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call cmout (logfil , ncv, ncv , & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ctrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv2 , conds , sep , & workev , ncv , ierr) c if (nconv2 .lt. nconv) then nconv = nconv2 end if if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call cvout (logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call cmout(logfil , ncv, ncv , & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if c end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call ccopy(ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call ccopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call cgeqr2(ncv , nconv , workl(invsub), & ldq , workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using cunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call cunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr) call clacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( real( workl(invsub+(j-1)*ldq+j-1) ) .lt. & real(zero) ) then call cscal(nconv, -one, workl(iuptri+j-1), ldq) call cscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ctrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ctrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = scnrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = real(one) / rtemp call csscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = cdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call ccopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call cvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call cmout(logfil , ncv, ncv , & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call ccopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ctrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed CNAUPD into D. | c %--------------------------------------------------% c call ccopy(nconv, workl(ritz), 1, d, 1) call ccopy(nconv, workl(ritz), 1, workl(iheig), 1) call ccopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call cscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call cvout (logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call cvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call cvout (logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call cvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) / & workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call cgeru (n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %---------------% c | End of cneupd| c %---------------% c end arpack-ng-3.3.0/SRC/cngets.f000066400000000000000000000126731260666001200154510ustar00rootroot00000000000000c\BeginDoc c c\Name: cngets c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call cngets c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex c c\Routines called: c csortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c cvout ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ngets.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine cngets ( ishift, which, kev, np, ritz, bounds) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex & one, zero parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external cvout, csortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call csortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine cnapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call csortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is') call ivout (logfil, 1, np, ndigit, '_ngets: NP is') call cvout (logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call cvout (logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %---------------% c | End of cngets | c %---------------% c end arpack-ng-3.3.0/SRC/csortc.f000066400000000000000000000175751260666001200154710ustar00rootroot00000000000000c\BeginDoc c c\Name: csortc c c\Description: c Sorts the Complex array in X into the order c specified by WHICH and optionally applies the permutation to the c Real array Y. c c\Usage: c call csortc c ( WHICH, APPLY, N, X, Y ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> sort X into increasing order of magnitude. c 'SM' -> sort X into decreasing order of magnitude. c 'LR' -> sort X with real(X) in increasing algebraic order c 'SR' -> sort X with real(X) in decreasing algebraic order c 'LI' -> sort X with imag(X) in increasing algebraic order c 'SI' -> sort X with imag(X) in decreasing algebraic order c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to array Y. c APPLY = .FALSE. -> do not apply the sorted order to array Y. c c N Integer. (INPUT) c Size of the arrays. c c X Complex array of length N. (INPUT/OUTPUT) c This is the array to be sorted. c c Y Complex array of length N. (INPUT/OUTPUT) c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines called: c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortc.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine csortc (which, apply, n, x, y) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Complex & x(0:n-1), y(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Complex & temp Real & temp1, temp2 c c %--------------------% c | External functions | c %--------------------% c Real & slapy2 c c %--------------------% c | Intrinsic Functions | c %--------------------% Intrinsic & real, aimag c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'LM') then c c %--------------------------------------------% c | Sort X into increasing order of magnitude. | c %--------------------------------------------% c 10 continue if (igap .eq. 0) go to 9000 c do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c temp1 = slapy2(real(x(j)),aimag(x(j))) temp2 = slapy2(real(x(j+igap)),aimag(x(j+igap))) c if (temp1.gt.temp2) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 30 end if j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c %--------------------------------------------% c | Sort X into decreasing order of magnitude. | c %--------------------------------------------% c 40 continue if (igap .eq. 0) go to 9000 c do 60 i = igap, n-1 j = i-igap 50 continue c if (j .lt. 0) go to 60 c temp1 = slapy2(real(x(j)),aimag(x(j))) temp2 = slapy2(real(x(j+igap)),aimag(x(j+igap))) c if (temp1.lt.temp2) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LR') then c c %------------------------------------------------% c | Sort XREAL into increasing order of algebraic. | c %------------------------------------------------% c 70 continue if (igap .eq. 0) go to 9000 c do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (real(x(j)).gt.real(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'SR') then c c %------------------------------------------------% c | Sort XREAL into decreasing order of algebraic. | c %------------------------------------------------% c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (real(x(j)).lt.real(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 c else if (which .eq. 'LI') then c c %--------------------------------------------% c | Sort XIMAG into increasing algebraic order | c %--------------------------------------------% c 130 continue if (igap .eq. 0) go to 9000 do 150 i = igap, n-1 j = i-igap 140 continue c if (j.lt.0) go to 150 c if (aimag(x(j)).gt.aimag(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 150 endif j = j-igap go to 140 150 continue igap = igap / 2 go to 130 c else if (which .eq. 'SI') then c c %---------------------------------------------% c | Sort XIMAG into decreasing algebraic order | c %---------------------------------------------% c 160 continue if (igap .eq. 0) go to 9000 do 180 i = igap, n-1 j = i-igap 170 continue c if (j.lt.0) go to 180 c if (aimag(x(j)).lt.aimag(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 180 endif j = j-igap go to 170 180 continue igap = igap / 2 go to 160 end if c 9000 continue return c c %---------------% c | End of csortc | c %---------------% c end arpack-ng-3.3.0/SRC/cstatn.f000066400000000000000000000023051260666001200154510ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: statn.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c %---------------------------------------------% c | Initialize statistic and timing information | c | for complex nonsymmetric Arnoldi code. | c %---------------------------------------------% subroutine cstatn c c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c include 'stat.h' c %-----------------------% c | Executable Statements | c %-----------------------% nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 tcaupd = 0.0E+0 tcaup2 = 0.0E+0 tcaitr = 0.0E+0 tceigh = 0.0E+0 tcgets = 0.0E+0 tcapps = 0.0E+0 tcconv = 0.0E+0 titref = 0.0E+0 tgetv0 = 0.0E+0 trvec = 0.0E+0 c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% tmvopx = 0.0E+0 tmvbx = 0.0E+0 return c c %---------------% c | End of cstatn | c %---------------% c end arpack-ng-3.3.0/SRC/debug.h000066400000000000000000000013511260666001200152450ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/SRC/dgetv0.f000066400000000000000000000316421260666001200153540ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dgetv0 c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call dgetv0 c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, IERR ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to dgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that dgetv0 is called. c It should be set to 1 on the initial call to dgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Double precision N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Double precision work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine for vector output. c dlarnv LAPACK routine for generating a random vector. c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: getv0.F SID: 2.7 DATE OF SID: 04/07/99 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine dgetv0 & ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & resid(n), v(ldv,j), workd(2*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Double precision & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external dlarnv, dvout, dcopy, dgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, dnrm2 external ddot, dnrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call dlarnv (idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call dcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c if (bmat .eq. 'G') then call arscnd (t3) tmvopx = tmvopx + (t3 - t2) end if c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then rnorm0 = ddot (n, resid, 1, workd, 1) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = dnrm2(n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call dgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workd(n+1), 1) call dgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = dnrm2(n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call dvout (logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call dvout (logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call dvout (logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 3) then call dvout (logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %---------------% c | End of dgetv0 | c %---------------% c end arpack-ng-3.3.0/SRC/dnaitr.f000066400000000000000000000736731260666001200154560ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dnaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in dnaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call dnaitr c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See dnaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c dgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dlabad LAPACK routine that computes machine constants. c dlamch LAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dlanhs LAPACK routine that computes various norms of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: naitr.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in dnaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine dnaitr & (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, dgetv0, dlabad, & dvout, dmout, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, dnrm2, dlanhs, dlamch external ddot, dnrm2, dlanhs, dlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------% c unfl = dlamch( 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = dlamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | dgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call ivout (logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call dvout (logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call dgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then wnorm = ddot (n, resid, 1, workd(ipj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = dnrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd(ipj), 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = dnrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call dvout (logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call dvout (logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) call daxpy (j, one, workd(irj), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = ddot (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = dnrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call dvout (logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call dmout (logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of dnaitr | c %---------------% c end arpack-ng-3.3.0/SRC/dnapps.f000066400000000000000000000557211260666001200154540ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dnapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call dnapps c ( N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Double precision array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to dnapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices. c dvout ARPACK utility routine that prints vectors. c dlabad LAPACK routine that computes machine constants. c dlacpy LAPACK matrix copy routine. c dlamch LAPACK routine that determines machine constants. c dlanhs LAPACK routine that computes various norms of a matrix. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlarf LAPACK routine that applies Householder reflection to c a matrix. c dlarfg LAPACK Householder reflection construction routine. c dlartg LAPACK Givens rotation construction routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another . c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: napps.F SID: 2.4 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine dlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine dnapps & ( n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Double precision & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlarfg, dlarf, & dlaset, dlabad, arscnd, dlartg c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlamch, dlanhs, dlapy2 external dlamch, dlanhs, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine dlahqr | c %-----------------------------------------------% c unfl = dlamch( 'safe minimum' ) ovfl = one / unfl call dlabad( unfl, ovfl ) ulp = dlamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call ivout (logfil, 1, jj, ndigit, & '_napps: shift number.') call dvout (logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call dvout (logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call dvout (logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, istart, ndigit, & '_napps: Start of current block ') call ivout (logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call dlartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = dlapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call dlarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call dlarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call dlarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call dlarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call dscal( kplusp-j+1, -one, h(j+1,j), ldh ) call dscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call dscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine dlahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = dlanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call daxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call dvout (logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call dvout (logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call ivout (logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call dmout (logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %---------------% c | End of dnapps | c %---------------% c end arpack-ng-3.3.0/SRC/dnaup2.f000066400000000000000000000762201260666001200153550ustar00rootroot00000000000000c\BeginDoc c c\Name: dnaup2 c c\Description: c Intermediate level interface called by dnaupd . c c\Usage: c call dnaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in dnaupd . c MODE, ISHIFT, MXITER: see the definition of IPARAM in dnaupd . c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from dneigh . c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c dgetv0 ARPACK initial vector generation routine. c dnaitr ARPACK Arnoldi factorization routine. c dnapps ARPACK application of implicit shifts routine. c dnconv ARPACK convergence of Ritz values routine. c dneigh ARPACK compute Ritz values and error bounds routine. c dngets ARPACK reorder Ritz values and error bounds routine. c dsortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naup2.F SID: 2.8 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine dnaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Double precision & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0 , zero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv, update, ushift integer ierr , iter , j , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv Double precision & rnorm , temp , eps23 save cnorm , getv0, initv, update, ushift, & rnorm , iter , eps23, kplusp, msglvl, nconv , & nevbef, nev0 , np0 , numcnv c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dgetv0 , dnaitr , dnconv , dneigh , & dngets , dnapps , dvout , ivout , arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot , dnrm2 , dlapy2 , dlamch external ddot , dnrm2 , dlapy2 , dlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = dlamch ('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call dgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call dnaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine dnapps . | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call ivout (logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call dnaitr (ido , bmat, n , nev, np , mode , resid, & rnorm, v , ldv, h , ldh, ipntr, workd, & info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call dvout (logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call dneigh (rnorm, kplusp, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from dneigh . | c %----------------------------------------------------% c call dcopy (kplusp, ritzr, 1, workl(kplusp**2+1), 1) call dcopy (kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call dcopy (kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of dngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call dngets (ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call dnconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call ivout (logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call dvout (logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call dvout (logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call dvout (logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call dvout (logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call dvout (logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with dngets , we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in dngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call dsortc (wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, dlapy2 (ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call dsortc (which, .true., nconv, ritzr, ritzi, bounds) c if (msglvl .gt. 1) then call dvout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call dvout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call dvout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if c %---- Scipy fix ------------------------------------------------ c | We must keep nev below this value, as otherwise we can get c | np == 0 (note that dngets below can bump nev by 1). If np == 0, c | the next call to `dnaitr` will write out-of-bounds. c | if (nev .gt. kplusp - 2) then nev = kplusp - 2 end if c | c %---- Scipy fix end -------------------------------------------- c np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call dngets (ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call dvout (logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call dvout (logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call dvout (logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call dcopy (np, workl, 1, ritzr, 1) call dcopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call dvout (logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call dvout (logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call dvout (logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call dnapps (n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to dnaitr . | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = dnrm2 (n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call dvout (logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call dmout (logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %---------------% c | End of dnaup2 | c %---------------% c return end arpack-ng-3.3.0/SRC/dnaupd.f000066400000000000000000000720261260666001200154370ustar00rootroot00000000000000c\BeginDoc c c\Name: dnaupd c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine dsaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c dnaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call dnaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to dnaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c dnaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT/OUTPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Double precision array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of dnaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), dnaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by dneupd . See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c dneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine dneupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine dneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call dneupd immediately following c completion of dnaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Double precision resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Double precision resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c dnaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version '1.1' c c\SCCS Information: @(#) c FILE: naupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine dnaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0 , zero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external dnaup2 , dvout , ivout, arscnd, dstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlamch external dlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = dlamch ('EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine dneigh called | c | by dnaup2 . Subroutine dneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call dnaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within dnaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call dvout (logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call dvout (logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call dvout (logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.4' , 21x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if c 9000 continue c return c c %---------------% c | End of dnaupd | c %---------------% c end arpack-ng-3.3.0/SRC/dnconv.f000066400000000000000000000077651260666001200154630ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dnconv c c\Description: c Convergence testing for the nonsymmetric Arnoldi eigenvalue routine. c c\Usage: c call dnconv c ( N, RITZR, RITZI, BOUNDS, TOL, NCONV ) c c\Arguments c N Integer. (INPUT) c Number of Ritz values to check for convergence. c c RITZR, Double precision arrays of length N. (INPUT) c RITZI Real and imaginary parts of the Ritz values to be checked c for convergence. c BOUNDS Double precision array of length N. (INPUT) c Ritz estimates for the Ritz values in RITZR and RITZI. c c TOL Double precision scalar. (INPUT) c Desired backward error for a Ritz value to be considered c "converged". c c NCONV Integer scalar. (OUTPUT) c Number of "converged" Ritz values. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c arscnd ARPACK utility routine for timing. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: nconv.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine dnconv (n, ritzr, ritzi, bounds, tol, nconv) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer n, nconv Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% Double precision & ritzr(n), ritzi(n), bounds(n) c c %---------------% c | Local Scalars | c %---------------% c integer i Double precision & temp, eps23 c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2, dlamch external dlapy2, dlamch c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------------------% c | Convergence test: unlike in the symmetric code, I am not | c | using things like refined error bounds and gap condition | c | because I don't know the exact equivalent concept. | c | | c | Instead the i-th Ritz value is considered "converged" when: | c | | c | bounds(i) .le. ( TOL * | ritz | ) | c | | c | for some appropriate choice of norm. | c %-------------------------------------------------------------% c call arscnd (t0) c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = dlamch('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0) c nconv = 0 do 20 i = 1, n temp = max( eps23, dlapy2( ritzr(i), ritzi(i) ) ) if (bounds(i) .le. tol*temp) nconv = nconv + 1 20 continue c call arscnd (t1) tnconv = tnconv + (t1 - t0) c return c c %---------------% c | End of dnconv | c %---------------% c end arpack-ng-3.3.0/SRC/dneigh.f000066400000000000000000000244041260666001200154170ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dneigh c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call dneigh c ( RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Double precision N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Double precision arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Double precision N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from dlahqr or dtrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dlahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dlacpy LAPACK matrix copy routine. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c dgemv Level 2 BLAS routine for matrix vector multiplication. c dcopy Level 1 BLAS that copies one vector to another . c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: neigh.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine dneigh (rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Double precision & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dlacpy, dlahqr, dtrevc, dvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call dmout (logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | dlahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call dlacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = 1 call dlahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call dvout (logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call dtrevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = dnrm2( n, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2( dnrm2( n, q(1,i), 1 ), & dnrm2( n, q(1,i+1), 1 ) ) call dscal ( n, one / temp, q(1,i), 1 ) call dscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call dgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call dvout (logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * dlapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call dvout (logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call dvout (logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call dvout (logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %---------------% c | End of dneigh | c %---------------% c end arpack-ng-3.3.0/SRC/dneupd.f000066400000000000000000001266151260666001200154470ustar00rootroot00000000000000c\BeginDoc c c\Name: dneupd c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to DNAUPD . DNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine DNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of DNAUPD . c c\Usage: c call dneupd c ( RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, c LWORKL, INFO ) c c\Arguments: c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Double precision array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c DNAUPD . A further computation must be performed by the user c to transform the Ritz values computed for OP by DNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Double precision array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Double precision N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by DNAUPD . In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Double precision (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Double precision work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to DNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to DNEUPD following the last call c to DNAUPD . These arguments MUST NOT BE MODIFIED between c the the last call to DNAUPD and the call to DNEUPD . c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Double precision N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by DNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c dnaupd . They are not changed by dneupd . c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by dneupd . c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c dneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine dlahqr c could not be reordered by LAPACK routine dtrsen . c Re-enter subroutine dneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine dlahqr . c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine dtrevc . c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: DNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: DNEUPD got a different count of the number of converged c Ritz values than DNAUPD got. This indicates the user c probably made an error in passing data from DNAUPD to c DNEUPD or that the data was modified before entering c DNEUPD c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c ivout ARPACK utility routine that prints integers. c dmout ARPACK utility routine that prints matrices c dvout ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c dlahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlaset LAPACK matrix initialization routine. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dtrevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c dtrsen LAPACK routine that re-orders the Schur form. c dtrmm Level 3 BLAS matrix times an upper triangular matrix. c dger Level 2 BLAS rank one update to a matrix. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let trans(X) denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c trans(V(:,1:IPARAM(5))) * V(:,1:IPARAM(5)) = I are approximately c satisfied. Here T is the leading submatrix of order IPARAM(5) of the c real upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by DNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c trans(Z(:,I)) * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c trans(Z(:,I)) * A * Z(:,I) + trans(Z(:,I+1)) * A * Z(:,I+1), c trans(Z(:,I)) * A * Z(:,I+1) - trans(Z(:,I+1)) * A * Z(:,I), c respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute trans(V(:,1:IPARAM(5))) * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neupd.F SID: 2.7 DATE OF SID: 09/20/00 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine dneupd (rvec , howmny, select, dr , di, & z , ldz , sigmar, sigmai, workev, & bmat , n , which , nev , tol, & resid, ncv , v , ldv , iparam, & ipntr, workd , workl , lworkl, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & dr(nev+1) , di(nev+1), resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0 , zero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds , & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj , nconv2 logical reord Double precision & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2 , dlacpy , & dlahqr , dlaset , dmout , dorm2r , & dtrevc , dtrmm , dtrsen , dscal , & dvout , ivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2 , dnrm2 , dlamch , ddot external dlapy2 , dnrm2 , dlamch , ddot c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = dlamch ('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by DNEUPD . | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call dvout (logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call dvout (logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call dngets (ishift , which , nev , & np , workl(irr), workl(iri), & workl(bounds), workl , workl(np+1)) c if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call dvout (logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call dvout (logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & dlapy2 ( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine dlahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by DNAUPD . | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ldh*ncv, workl(ih), 1, workl(iuptri), 1) call dlaset ('All', ncv, ncv, & zero , one, workl(invsub), & ldq) call dlahqr (.true., .true. , ncv, & 1 , ncv , workl(iuptri), & ldh , workl(iheigr), workl(iheigi), & 1 , ncv , workl(invsub), & ldq , ierr) call dcopy (ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call dvout (logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call dvout (logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call dvout (logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call dmout (logfil , ncv, ncv , & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call dtrsen ('None' , 'V' , & select , ncv , & workl(iuptri), ldh , & workl(invsub), ldq , & workl(iheigr), workl(iheigi), & nconv2 , conds , & sep , workl(ihbds) , & ncv , iwork , & 1 , ierr) c if (nconv2 .lt. nconv) then nconv = nconv2 end if if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call dvout (logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call dmout (logfil , ncv, ncv , & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if c end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call dcopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using dorm2r . | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr) call dlacpy ('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call dscal (nconv, -one, workl(iuptri+j-1), ldq) call dscal (nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call dtrevc ('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | dtrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = dnrm2 ( ncv, workl(invsub+(j-1)*ldq), 1 ) call dscal ( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) c else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = dlapy2 (dnrm2 (ncv, & workl(invsub+(j-1)*ldq), & 1), & dnrm2 (ncv, & workl(invsub+j*ldq), & 1)) call dscal (ncv, one/temp, & workl(invsub+(j-1)*ldq), 1 ) call dscal (ncv, one/temp, & workl(invsub+j*ldq), 1 ) iconj = 1 else iconj = 0 end if c end if c 40 continue c call dgemv ('T', ncv, nconv, one, workl(invsub), & ldq, workl(ihbds), 1, zero, workev, 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = dlapy2 (workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call dcopy (ncv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call dvout (logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call dmout (logfil, ncv, ncv, workl(invsub), ldq, & ndigit, '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call dcopy (nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call dtrmm ('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed DNAUPD into DR and DI | c %------------------------------------------------------% c call dcopy (nconv, workl(ritzr), 1, dr, 1) call dcopy (nconv, workl(ritzi), 1, di, 1) call dcopy (nconv, workl(ritzr), 1, workl(iheigr), 1) call dcopy (nconv, workl(ritzi), 1, workl(iheigi), 1) call dcopy (nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call dscal (ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = dlapy2 ( workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = dlapy2 ( workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1)/temp/temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1)/temp/temp & + sigmai 80 continue c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call dcopy (nconv, workl(iheigr), 1, dr, 1) call dcopy (nconv, workl(iheigi), 1, di, 1) c end if c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call dvout (logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call dvout (logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call dvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call dvout (logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call dvout (logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call dvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) / & workl(iheigr+j-1) else if (iconj .eq. 0) then temp = dlapy2 ( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call dger (n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %---------------% c | End of DNEUPD | c %---------------% c end arpack-ng-3.3.0/SRC/dngets.f000066400000000000000000000175341260666001200154530ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dngets c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call dngets c ( ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Double precision array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortc ARPACK sorting routine. c dcopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: ngets.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine dngets ( ishift, which, kev, np, ritzr, ritzi, bounds, & shiftr, shifti ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dsortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call dsortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call dsortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call dsortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine dnapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call dsortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is') call ivout (logfil, 1, np, ndigit, '_ngets: NP is') call dvout (logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call dvout (logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call dvout (logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %---------------% c | End of dngets | c %---------------% c end arpack-ng-3.3.0/SRC/dsaitr.f000066400000000000000000000741331260666001200154530ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in dsaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call dsaitr c ( IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See dsaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Double precision N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c dmout ARPACK utility routine that prints matrices. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c dlascl LAPACK routine for careful scaling of a matrix. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dscal Level 1 BLAS that scales a vector. c dcopy Level 1 BLAS that copies one vector to another . c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: saitr.F SID: 2.6 DATE OF SID: 8/28/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in dsaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine dsaitr & (ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, & infol, jj Double precision & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Double precision & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dgemv, dgetv0, dvout, dmout, & dlascl, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, dnrm2, dlamch external ddot, dnrm2, dlamch c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = dlamch('safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | dgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call dvout (logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call dgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call dcopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call dscal (n, temp1, v(1,j), 1) call dscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call dlascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call dlascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call dcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call dcopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c wnorm = ddot (n, resid, 1, workd(ivj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then wnorm = ddot (n, resid, 1, workd(ipj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = dnrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call dgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workd(irj), 1) else if (mode .eq. 2) then call dgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workd(irj), 1) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call dgemv('N', n, j, -one, v, ldv, workd(irj), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workd(irj + j - 1) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd(ipj), 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = dnrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call dvout (logfil, 2, xtemp, ndigit, & '_saitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call dgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workd(irj + j - 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = ddot (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = dnrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_saitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call dvout (logfil, 2, xtemp, ndigit, & '_saitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call dscal(n, -one, v(1,j+1), 1) else call dscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call dvout (logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call dvout (logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of dsaitr | c %---------------% c end arpack-ng-3.3.0/SRC/dsapps.f000066400000000000000000000441221260666001200154520ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call dsapps c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Double precision array of length NP. (INPUT) c The shifts to be applied. c c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Double precision array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Double precision work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c dlartg LAPACK Givens rotation construction routine. c dlacpy LAPACK matrix copy routine. c dlaset LAPACK matrix initialization routine. c dgemv Level 2 BLAS routine for matrix vector multiplication. c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another. c dscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: sapps.F SID: 2.6 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine dsapps & ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Double precision & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external daxpy, dcopy, dscal, dlacpy, dlartg, dlaset, dvout, & ivout, arscnd, dgemv c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlamch external dlamch c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = dlamch('Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call dlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call dvout (logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call dlartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call dscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call dvout (logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call dgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call dcopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call dlacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call dcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call dscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call daxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call dvout (logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call dvout (logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call dvout (logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call dvout (logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %---------------% c | End of dsapps | c %---------------% c end arpack-ng-3.3.0/SRC/dsaup2.f000066400000000000000000000771741260666001200153730ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsaup2 c c\Description: c Intermediate level interface called by dsaupd. c c\Usage: c call dsaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in dsaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in dsaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Double precision (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the arscnd column c of H starting at H(1,2). If dsaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Double precision array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Double precision array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Double precision array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in dsaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c dgetv0 ARPACK initial vector generation routine. c dsaitr ARPACK Lanczos factorization routine. c dsapps ARPACK application of implicit shifts routine. c dsconv ARPACK convergence of Ritz values routine. c dseigt ARPACK compute Ritz values and error bounds routine. c dsgets ARPACK reorder Ritz values and error bounds routine. c dsortr ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c dcopy Level 1 BLAS that copies one vector to another. c ddot Level 1 BLAS that computes the scalar product of two vectors. c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.4' c xx/xx/95: Version ' 2.4'. (R.B. Lehoucq) c c\SCCS Information: @(#) c FILE: saup2.F SID: 2.7 DATE OF SID: 5/19/98 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine dsaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Double precision & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Double precision & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dgetv0, dsaitr, dscal, dsconv, dseigt, dsgets, & dsapps, dsortr, dvout, ivout, arscnd, dswap c c %--------------------% c | External Functions | c %--------------------% c Double precision & ddot, dnrm2, dlamch external ddot, dnrm2, dlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = dlamch('Epsilon-Machine') eps23 = eps23**(2.0D+0/3.0D+0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %--------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %--------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call dgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call dsaitr (ido, bmat, n, 0, nev0, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | dsaitr was unable to build an Lanczos factorization | c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call ivout (logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call dsaitr (ido, bmat, n, nev, np, mode, resid, rnorm, v, & ldv, h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | dsaitr was unable to build an Lanczos factorization | c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call dvout (logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call dseigt (rnorm, kplusp, h, ldh, ritz, bounds, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call dcopy(kplusp, ritz, 1, workl(kplusp+1), 1) call dcopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call dsgets (ishift, which, nev, np, ritz, bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call dcopy (nev, bounds(np+1), 1, workl(np+1), 1) call dsconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call ivout (logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call dvout (logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call dvout (logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call dsortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then np = kplusp - nev0 call dswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call dswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call dsortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call dsortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call dsortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call dvout (logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call dvout (logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call dsgets (ishift, which, nev, np, ritz, bounds, & workl) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_saup2: NEV and NP are') call dvout (logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call dvout (logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:*NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, dsgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call dcopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call dvout (logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call dvout (logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After dsapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call dsapps (n, nev, np, ritz, v, ldv, h, ldh, resid, q, ldq, & workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to dsaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call dcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call dcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = ddot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = dnrm2(n, resid, 1) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call dvout (logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call dvout (logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call dvout (logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %---------------% c | End of dsaup2 | c %---------------% c end arpack-ng-3.3.0/SRC/dsaupd.f000066400000000000000000000702621260666001200154440ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsaupd c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c dsaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call dsaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to dsaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c dsaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Double precision scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = DLAMCH ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine DLAMCH ). c c RESID Double precision array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Double precision N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of dsaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), dsaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by dseupd . See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c dseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine dseupd uses this output. c See Data Distribution Note below. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine dsteqr . c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine dseupd . c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call dseupd immediately following completion c of dsaupd . This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c dsaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c dstats ARPACK routine that initialize timing and other statistics c variables. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: saupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine dsaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Double precision & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0 , zero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external dsaup2 , dvout , ivout, arscnd, dstats c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlamch external dlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call dstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev .or. ncv .gt. n) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = dlamch ('EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call dsaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within dsaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call dvout (logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call dvout (logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.4' , 19x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if c 9000 continue c return c c %---------------% c | End of dsaupd | c %---------------% c end arpack-ng-3.3.0/SRC/dsconv.f000066400000000000000000000066021260666001200154550ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsconv c c\Description: c Convergence testing for the symmetric Arnoldi eigenvalue routine. c c\Usage: c call dsconv c ( N, RITZ, BOUNDS, TOL, NCONV ) c c\Arguments c N Integer. (INPUT) c Number of Ritz values to check for convergence. c c RITZ Double precision array of length N. (INPUT) c The Ritz values to be checked for convergence. c c BOUNDS Double precision array of length N. (INPUT) c Ritz estimates associated with the Ritz values in RITZ. c c TOL Double precision scalar. (INPUT) c Desired relative accuracy for a Ritz value to be considered c "converged". c c NCONV Integer scalar. (OUTPUT) c Number of "converged" Ritz values. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines called: c arscnd ARPACK utility routine for timing. c dlamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sconv.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2 c c\Remarks c 1. Starting with version 2.4, this routine no longer uses the c Parlett strategy using the gap conditions. c c\EndLib c c----------------------------------------------------------------------- c subroutine dsconv (n, ritz, bounds, tol, nconv) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer n, nconv Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & ritz(n), bounds(n) c c %---------------% c | Local Scalars | c %---------------% c integer i Double precision & temp, eps23 c c %-------------------% c | External routines | c %-------------------% c Double precision & dlamch external dlamch c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call arscnd (t0) c eps23 = dlamch('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0) c nconv = 0 do 10 i = 1, n c c %-----------------------------------------------------% c | The i-th Ritz value is considered "converged" | c | when: bounds(i) .le. TOL*max(eps23, abs(ritz(i))) | c %-----------------------------------------------------% c temp = max( eps23, abs(ritz(i)) ) if ( bounds(i) .le. tol*temp ) then nconv = nconv + 1 end if c 10 continue c call arscnd (t1) tsconv = tsconv + (t1 - t0) c return c c %---------------% c | End of dsconv | c %---------------% c end arpack-ng-3.3.0/SRC/dseigt.f000066400000000000000000000121151260666001200154340ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dseigt c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call dseigt c ( RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c RNORM Double precision scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Double precision N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Double precision array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Double precision array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Double precision work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from dstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: seigt.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine dseigt & ( rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy, dstqrb, dvout, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call dvout (logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call dvout (logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c call dcopy (n, h(1,2), 1, eig, 1) call dcopy (n-1, h(2,1), 1, workl, 1) call dstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 if (msglvl .gt. 1) then call dvout (logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %---------------% c | End of dseigt | c %---------------% c end arpack-ng-3.3.0/SRC/dsesrt.f000066400000000000000000000123701260666001200154640ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsesrt c c\Description: c Sort the array X in the order specified by WHICH and optionally c apply the permutation to the columns of the matrix A. c c\Usage: c call dsesrt c ( WHICH, APPLY, N, X, NA, A, LDA) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> X is sorted into increasing order of magnitude. c 'SM' -> X is sorted into decreasing order of magnitude. c 'LA' -> X is sorted into increasing order of algebraic. c 'SA' -> X is sorted into decreasing order of algebraic. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to A. c APPLY = .FALSE. -> do not apply the sorted order to A. c c N Integer. (INPUT) c Dimension of the array X. c c X Double precision array of length N. (INPUT/OUTPUT) c The array to be sorted. c c NA Integer. (INPUT) c Number of rows of the matrix A. c c A Double precision array of length NA by N. (INPUT/OUTPUT) c c LDA Integer. (INPUT) c Leading dimension of A. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines c dswap Level 1 BLAS that swaps the contents of two vectors. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.1'. c Adapted from the sort routine in LANSO and c the ARPACK code dsortr c c\SCCS Information: @(#) c FILE: sesrt.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine dsesrt (which, apply, n, x, na, a, lda) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer lda, n, na c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & x(0:n-1), a(lda, 0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Double precision & temp c c %----------------------% c | External Subroutines | c %----------------------% c external dswap c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'SA') then c c X is sorted into decreasing order of algebraic. c 10 continue if (igap .eq. 0) go to 9000 do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c if (x(j).lt.x(j+igap)) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 30 endif j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c X is sorted into decreasing order of magnitude. c 40 continue if (igap .eq. 0) go to 9000 do 60 i = igap, n-1 j = i-igap 50 continue c if (j.lt.0) go to 60 c if (abs(x(j)).lt.abs(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LA') then c c X is sorted into increasing order of algebraic. c 70 continue if (igap .eq. 0) go to 9000 do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (x(j).gt.x(j+igap)) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'LM') then c c X is sorted into increasing order of magnitude. c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (abs(x(j)).gt.abs(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 end if c 9000 continue return c c %---------------% c | End of dsesrt | c %---------------% c end arpack-ng-3.3.0/SRC/dseupd.f000066400000000000000000001040501260666001200154410ustar00rootroot00000000000000c\BeginDoc c c\Name: dseupd c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by DSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in DSAUPD documentation.) DSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine DSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call dseupd c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as a workspace for c reordering the Ritz values. c c D Double precision array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by dsaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by DSAUPD . c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Double precision (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to DSAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to DSEUPD following the last call c to DSAUPD . These arguments MUST NOT BE MODIFIED between c the the last call to DSAUPD and the call to DSEUPD . c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c dsaupd . They are not changed by dseupd . c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointer into WORKL for addresses c of the above information computed by dseupd . c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c dseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine dsteqr . c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: DSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: DSEUPD got a different count of the number of converged c Ritz values than DSAUPD got. This indicates the user c probably made an error in passing data from DSAUPD to c DSEUPD or that the data was modified before entering c DSEUPD . c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c dsesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c dsortr dsortr ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c dvout ARPACK utility routine that prints vectors. c dgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c dlacpy LAPACK matrix copy routine. c dlamch LAPACK routine that determines machine constants. c dorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dsteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c dger Level 2 BLAS rank one update to a matrix. c dcopy Level 1 BLAS that copies one vector to another . c dnrm2 Level 1 BLAS that computes the norm of a vector. c dscal Level 1 BLAS that scales a vector. c dswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.1' c c\SCCS Information: @(#) c FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine dseupd (rvec , howmny, select, d , & z , ldz , sigma , bmat , & n , which , nev , tol , & resid , ncv , v , ldv , & iparam, ipntr , workd , workl, & lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Double precision & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Double precision & d(nev) , resid(n) , v(ldv,ncv), & z(ldz, nev), workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0 , zero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Double precision & bnorm2 , rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external dcopy , dger , dgeqr2 , dlacpy , dorm2r , dscal , & dsesrt , dsteqr , dswap , dvout , ivout , dsortr c c %--------------------% c | External Functions | c %--------------------% c Double precision & dnrm2 , dlamch external dnrm2 , dlamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev .or. ncv .gt. n) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | dsaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by dsaupd and is not | c | modified by dseupd . | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by dseupd . | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | dsteqr . Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by dsteqr and by dseupd . | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = dlamch ('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0 ) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of dsaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = dnrm2 (n, workd, 1) end if c if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call dvout (logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call dsgets (ishift, which , nev , & np , workl(irz) , workl(bounds), & workl) c if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call dvout (logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_seupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_seupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call dcopy (ncv-1, workl(ih+1), 1, workl(ihb), 1) call dcopy (ncv, workl(ih+ldh), 1, workl(ihd), 1) c call dsteqr ('Identity', ncv, workl(ihd), workl(ihb), & workl(iq) , ldq, workl(iw), ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call dcopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call dvout (logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call dvout (logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if ( .not. select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call dcopy (ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call dcopy (ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call dcopy (ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c end if c 30 if (msglvl .gt. 2) then call dvout (logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call dcopy (nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call dcopy (nconv, workl(ritz), 1, d, 1) call dcopy (ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call dsesrt ('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy (ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by dsaupd . | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call dcopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call dcopy (nconv, workl(ihd), 1, d, 1) call dsortr ('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call dsesrt ('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call dcopy (ncv, workl(bounds), 1, workl(ihb), 1) call dscal (ncv, bnorm2/rnorm, workl(ihb), 1) call dsortr ('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call dgeqr2 (ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call dorm2r ('Right', 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr) call dlacpy ('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call dorm2r ('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr) c c %-----------------------------------------------------% c | Make a copy of the last row into | c | workl(iw+ncv:iw+2*ncv), as it is needed again in | c | the Ritz vector purification step below | c %-----------------------------------------------------% c do 67 j = 1, nconv workl(iw+ncv+j-1) = workl(ihb+j-1) 67 continue else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by dsaupd . | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call dscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / (workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call dvout (logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call dvout (logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call dvout (logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call dvout (logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iw+ncv+k) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iw+ncv+k) & / (workl(iw+k)-one) 120 continue c end if c if (rvec .and. type .ne. 'REGULR') & call dger (n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %---------------% c | End of dseupd | c %---------------% c end arpack-ng-3.3.0/SRC/dsgets.f000066400000000000000000000164351260666001200154570ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsgets c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call dsgets c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Double precision array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Double precision array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c dsortr ARPACK utility sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c dvout ARPACK utility routine that prints vectors. c dcopy Level 1 BLAS that copies one vector to another. c dswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/93: Version ' 2.1' c c\SCCS Information: @(#) c FILE: sgets.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine dsgets ( ishift, which, kev, np, ritz, bounds, shifts ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Double precision & one, zero parameter (one = 1.0D+0, zero = 0.0D+0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external dswap, dcopy, dsortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call dsortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call dswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call dswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call dsortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine dsapps. | c %-------------------------------------------------------% c call dsortr ('SM', .true., np, bounds, ritz) call dcopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_sgets: KEV is') call ivout (logfil, 1, np, ndigit, '_sgets: NP is') call dvout (logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call dvout (logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %---------------% c | End of dsgets | c %---------------% c end arpack-ng-3.3.0/SRC/dsortc.f000066400000000000000000000220461260666001200154570ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsortc c c\Description: c Sorts the complex array in XREAL and XIMAG into the order c specified by WHICH and optionally applies the permutation to the c real array Y. It is assumed that if an element of XIMAG is c nonzero, then its negative is also an element. In other words, c both members of a complex conjugate pair are to be sorted and the c pairs are kept adjacent to each other. c c\Usage: c call dsortc c ( WHICH, APPLY, N, XREAL, XIMAG, Y ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> sort XREAL,XIMAG into increasing order of magnitude. c 'SM' -> sort XREAL,XIMAG into decreasing order of magnitude. c 'LR' -> sort XREAL into increasing order of algebraic. c 'SR' -> sort XREAL into decreasing order of algebraic. c 'LI' -> sort XIMAG into increasing order of magnitude. c 'SI' -> sort XIMAG into decreasing order of magnitude. c NOTE: If an element of XIMAG is non-zero, then its negative c is also an element. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to array Y. c APPLY = .FALSE. -> do not apply the sorted order to array Y. c c N Integer. (INPUT) c Size of the arrays. c c XREAL, Double precision array of length N. (INPUT/OUTPUT) c XIMAG Real and imaginary part of the array to be sorted. c c Y Double precision array of length N. (INPUT/OUTPUT) c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortc.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine dsortc (which, apply, n, xreal, ximag, y) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & xreal(0:n-1), ximag(0:n-1), y(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Double precision & temp, temp1, temp2 c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlapy2 external dlapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'LM') then c c %------------------------------------------------------% c | Sort XREAL,XIMAG into increasing order of magnitude. | c %------------------------------------------------------% c 10 continue if (igap .eq. 0) go to 9000 c do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c temp1 = dlapy2(xreal(j),ximag(j)) temp2 = dlapy2(xreal(j+igap),ximag(j+igap)) c if (temp1.gt.temp2) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 30 end if j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c %------------------------------------------------------% c | Sort XREAL,XIMAG into decreasing order of magnitude. | c %------------------------------------------------------% c 40 continue if (igap .eq. 0) go to 9000 c do 60 i = igap, n-1 j = i-igap 50 continue c if (j .lt. 0) go to 60 c temp1 = dlapy2(xreal(j),ximag(j)) temp2 = dlapy2(xreal(j+igap),ximag(j+igap)) c if (temp1.lt.temp2) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LR') then c c %------------------------------------------------% c | Sort XREAL into increasing order of algebraic. | c %------------------------------------------------% c 70 continue if (igap .eq. 0) go to 9000 c do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (xreal(j).gt.xreal(j+igap)) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'SR') then c c %------------------------------------------------% c | Sort XREAL into decreasing order of algebraic. | c %------------------------------------------------% c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (xreal(j).lt.xreal(j+igap)) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 c else if (which .eq. 'LI') then c c %------------------------------------------------% c | Sort XIMAG into increasing order of magnitude. | c %------------------------------------------------% c 130 continue if (igap .eq. 0) go to 9000 do 150 i = igap, n-1 j = i-igap 140 continue c if (j.lt.0) go to 150 c if (abs(ximag(j)).gt.abs(ximag(j+igap))) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 150 endif j = j-igap go to 140 150 continue igap = igap / 2 go to 130 c else if (which .eq. 'SI') then c c %------------------------------------------------% c | Sort XIMAG into decreasing order of magnitude. | c %------------------------------------------------% c 160 continue if (igap .eq. 0) go to 9000 do 180 i = igap, n-1 j = i-igap 170 continue c if (j.lt.0) go to 180 c if (abs(ximag(j)).lt.abs(ximag(j+igap))) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 180 endif j = j-igap go to 170 180 continue igap = igap / 2 go to 160 end if c 9000 continue return c c %---------------% c | End of dsortc | c %---------------% c end arpack-ng-3.3.0/SRC/dsortr.f000066400000000000000000000123541260666001200154770ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dsortr c c\Description: c Sort the array X1 in the order specified by WHICH and optionally c applies the permutation to the array X2. c c\Usage: c call dsortr c ( WHICH, APPLY, N, X1, X2 ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> X1 is sorted into increasing order of magnitude. c 'SM' -> X1 is sorted into decreasing order of magnitude. c 'LA' -> X1 is sorted into increasing order of algebraic. c 'SA' -> X1 is sorted into decreasing order of algebraic. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to X2. c APPLY = .FALSE. -> do not apply the sorted order to X2. c c N Integer. (INPUT) c Size of the arrays. c c X1 Double precision array of length N. (INPUT/OUTPUT) c The array to be sorted. c c X2 Double precision array of length N. (INPUT/OUTPUT) c Only referenced if APPLY = .TRUE. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version ' 2.1'. c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortr.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine dsortr (which, apply, n, x1, x2) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & x1(0:n-1), x2(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Double precision & temp c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'SA') then c c X1 is sorted into decreasing order of algebraic. c 10 continue if (igap .eq. 0) go to 9000 do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c if (x1(j).lt.x1(j+igap)) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 30 endif j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c X1 is sorted into decreasing order of magnitude. c 40 continue if (igap .eq. 0) go to 9000 do 60 i = igap, n-1 j = i-igap 50 continue c if (j.lt.0) go to 60 c if (abs(x1(j)).lt.abs(x1(j+igap))) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LA') then c c X1 is sorted into increasing order of algebraic. c 70 continue if (igap .eq. 0) go to 9000 do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (x1(j).gt.x1(j+igap)) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'LM') then c c X1 is sorted into increasing order of magnitude. c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (abs(x1(j)).gt.abs(x1(j+igap))) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 end if c 9000 continue return c c %---------------% c | End of dsortr | c %---------------% c end arpack-ng-3.3.0/SRC/dstatn.f000066400000000000000000000027101260666001200154520ustar00rootroot00000000000000c c %---------------------------------------------% c | Initialize statistic and timing information | c | for nonsymmetric Arnoldi code. | c %---------------------------------------------% c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: statn.F SID: 2.4 DATE OF SID: 4/20/96 RELEASE: 2 c subroutine dstatn c c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c include 'stat.h' c c %-----------------------% c | Executable Statements | c %-----------------------% c nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 c tnaupd = 0.0D+0 tnaup2 = 0.0D+0 tnaitr = 0.0D+0 tneigh = 0.0D+0 tngets = 0.0D+0 tnapps = 0.0D+0 tnconv = 0.0D+0 titref = 0.0D+0 tgetv0 = 0.0D+0 trvec = 0.0D+0 c c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% c tmvopx = 0.0D+0 tmvbx = 0.0D+0 c return c c c %---------------% c | End of dstatn | c %---------------% c end arpack-ng-3.3.0/SRC/dstats.f000066400000000000000000000022161260666001200154600ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: stats.F SID: 2.1 DATE OF SID: 4/19/96 RELEASE: 2 c %---------------------------------------------% c | Initialize statistic and timing information | c | for symmetric Arnoldi code. | c %---------------------------------------------% subroutine dstats c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% include 'stat.h' c %-----------------------% c | Executable Statements | c %-----------------------% nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 tsaupd = 0.0D+0 tsaup2 = 0.0D+0 tsaitr = 0.0D+0 tseigt = 0.0D+0 tsgets = 0.0D+0 tsapps = 0.0D+0 tsconv = 0.0D+0 titref = 0.0D+0 tgetv0 = 0.0D+0 trvec = 0.0D+0 c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% tmvopx = 0.0D+0 tmvbx = 0.0D+0 return c c End of dstats c end arpack-ng-3.3.0/SRC/dstqrb.f000066400000000000000000000406241260666001200154620ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: dstqrb c c\Description: c Computes all eigenvalues and the last component of the eigenvectors c of a symmetric tridiagonal matrix using the implicit QL or QR method. c c This is mostly a modification of the LAPACK routine dsteqr. c See Remarks. c c\Usage: c call dstqrb c ( N, D, E, Z, WORK, INFO ) c c\Arguments c N Integer. (INPUT) c The number of rows and columns in the matrix. N >= 0. c c D Double precision array, dimension (N). (INPUT/OUTPUT) c On entry, D contains the diagonal elements of the c tridiagonal matrix. c On exit, D contains the eigenvalues, in ascending order. c If an error exit is made, the eigenvalues are correct c for indices 1,2,...,INFO-1, but they are unordered and c may not be the smallest eigenvalues of the matrix. c c E Double precision array, dimension (N-1). (INPUT/OUTPUT) c On entry, E contains the subdiagonal elements of the c tridiagonal matrix in positions 1 through N-1. c On exit, E has been destroyed. c c Z Double precision array, dimension (N). (OUTPUT) c On exit, Z contains the last row of the orthonormal c eigenvector matrix of the symmetric tridiagonal matrix. c If an error exit is made, Z contains the last row of the c eigenvector matrix associated with the stored eigenvalues. c c WORK Double precision array, dimension (max(1,2*N-2)). (WORKSPACE) c Workspace used in accumulating the transformation for c computing the last components of the eigenvectors. c c INFO Integer. (OUTPUT) c = 0: normal return. c < 0: if INFO = -i, the i-th argument had an illegal value. c > 0: if INFO = +i, the i-th eigenvalue has not converged c after a total of 30*N iterations. c c\Remarks c 1. None. c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c daxpy Level 1 BLAS that computes a vector triad. c dcopy Level 1 BLAS that copies one vector to another. c dswap Level 1 BLAS that swaps the contents of two vectors. c lsame LAPACK character comparison routine. c dlae2 LAPACK routine that computes the eigenvalues of a 2-by-2 c symmetric matrix. c dlaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric c matrix. c dlamch LAPACK routine that determines machine constants. c dlanst LAPACK routine that computes the norm of a matrix. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c dlartg LAPACK Givens rotation construction routine. c dlascl LAPACK routine for careful scaling of a matrix. c dlaset LAPACK matrix initialization routine. c dlasr LAPACK routine that applies an orthogonal transformation to c a matrix. c dlasrt LAPACK sorting routine. c dsteqr LAPACK routine that computes eigenvalues and eigenvectors c of a symmetric tridiagonal matrix. c xerbla LAPACK error handler routine. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c 1. Starting with version 2.5, this routine is a modified version c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted, c only commeted out and new lines inserted. c All lines commented out have "c$$$" at the beginning. c Note that the LAPACK version 1.0 subroutine SSTEQR contained c bugs. c c\EndLib c c----------------------------------------------------------------------- c subroutine dstqrb ( n, d, e, z, work, info ) c c %------------------% c | Scalar Arguments | c %------------------% c integer info, n c c %-----------------% c | Array Arguments | c %-----------------% c Double precision & d( n ), e( n-1 ), z( n ), work( 2*n-2 ) c c .. parameters .. Double precision & zero, one, two, three parameter ( zero = 0.0D+0, one = 1.0D+0, & two = 2.0D+0, three = 3.0D+0 ) integer maxit parameter ( maxit = 30 ) c .. c .. local scalars .. integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend, & lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1, & nm1, nmaxit Double precision & anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2, & s, safmax, safmin, ssfmax, ssfmin, tst c .. c .. external functions .. logical lsame Double precision & dlamch, dlanst, dlapy2 external lsame, dlamch, dlanst, dlapy2 c .. c .. external subroutines .. external dlae2, dlaev2, dlartg, dlascl, dlaset, dlasr, & dlasrt, dswap, xerbla c .. c .. intrinsic functions .. intrinsic abs, max, sign, sqrt c .. c .. executable statements .. c c test the input parameters. c info = 0 c c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN c$$$ ICOMPZ = 0 c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN c$$$ ICOMPZ = 1 c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN c$$$ ICOMPZ = 2 c$$$ ELSE c$$$ ICOMPZ = -1 c$$$ END IF c$$$ IF( ICOMPZ.LT.0 ) THEN c$$$ INFO = -1 c$$$ ELSE IF( N.LT.0 ) THEN c$$$ INFO = -2 c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1, c$$$ $ N ) ) ) THEN c$$$ INFO = -6 c$$$ END IF c$$$ IF( INFO.NE.0 ) THEN c$$$ CALL XERBLA( 'SSTEQR', -INFO ) c$$$ RETURN c$$$ END IF c c *** New starting with version 2.5 *** c icompz = 2 c ************************************* c c quick return if possible c if( n.eq.0 ) $ return c if( n.eq.1 ) then if( icompz.eq.2 ) z( 1 ) = one return end if c c determine the unit roundoff and over/underflow thresholds. c eps = dlamch( 'e' ) eps2 = eps**2 safmin = dlamch( 's' ) safmax = one / safmin ssfmax = sqrt( safmax ) / three ssfmin = sqrt( safmin ) / eps2 c c compute the eigenvalues and eigenvectors of the tridiagonal c matrix. c c$$ if( icompz.eq.2 ) c$$$ $ call dlaset( 'full', n, n, zero, one, z, ldz ) c c *** New starting with version 2.5 *** c if ( icompz .eq. 2 ) then do 5 j = 1, n-1 z(j) = zero 5 continue z( n ) = one end if c ************************************* c nmaxit = n*maxit jtot = 0 c c determine where the matrix splits and choose ql or qr iteration c for each block, according to whether top or bottom diagonal c element is smaller. c l1 = 1 nm1 = n - 1 c 10 continue if( l1.gt.n ) $ go to 160 if( l1.gt.1 ) $ e( l1-1 ) = zero if( l1.le.nm1 ) then do 20 m = l1, nm1 tst = abs( e( m ) ) if( tst.eq.zero ) $ go to 30 if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+ $ 1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if 20 continue end if m = n c 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1 if( lend.eq.l ) $ go to 10 c c scale submatrix in rows and columns l to lend c anorm = dlanst( 'i', lend-l+1, d( l ), e( l ) ) iscale = 0 if( anorm.eq.zero ) $ go to 10 if( anorm.gt.ssfmax ) then iscale = 1 call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n, $ info ) call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n, $ info ) else if( anorm.lt.ssfmin ) then iscale = 2 call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n, $ info ) call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n, $ info ) end if c c choose between ql and qr iteration c if( abs( d( lend ) ).lt.abs( d( l ) ) ) then lend = lsv l = lendsv end if c if( lend.gt.l ) then c c ql iteration c c look for small subdiagonal element. c 40 continue if( l.ne.lend ) then lendm1 = lend - 1 do 50 m = l, lendm1 tst = abs( e( m ) )**2 if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+ $ safmin )go to 60 50 continue end if c m = lend c 60 continue if( m.lt.lend ) $ e( m ) = zero p = d( l ) if( m.eq.l ) $ go to 80 c c if remaining matrix is 2-by-2, use dlae2 or dlaev2 c to compute its eigensystem. c if( m.eq.l+1 ) then if( icompz.gt.0 ) then call dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s c$$$ call dlasr( 'r', 'v', 'b', n, 2, work( l ), c$$$ $ work( n-1+l ), z( 1, l ), ldz ) c c *** New starting with version 2.5 *** c tst = z(l+1) z(l+1) = c*tst - s*z(l) z(l) = s*tst + c*z(l) c ************************************* else call dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2 if( l.le.lend ) $ go to 40 go to 140 end if c if( jtot.eq.nmaxit ) $ go to 140 jtot = jtot + 1 c c form shift. c g = ( d( l+1 )-p ) / ( two*e( l ) ) r = dlapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) c s = one c = one p = zero c c inner loop c mm1 = m - 1 do 70 i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call dlartg( g, f, c, s, r ) if( i.ne.m-1 ) $ e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b c c if eigenvectors are desired, then save rotations. c if( icompz.gt.0 ) then work( i ) = c work( n-1+i ) = -s end if c 70 continue c c if eigenvectors are desired, then apply saved rotations. c if( icompz.gt.0 ) then mm = m - l + 1 c$$$ call dlasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ), c$$$ $ z( 1, l ), ldz ) c c *** New starting with version 2.5 *** c call dlasr( 'r', 'v', 'b', 1, mm, work( l ), & work( n-1+l ), z( l ), 1 ) c ************************************* end if c d( l ) = d( l ) - p e( l ) = g go to 40 c c eigenvalue found. c 80 continue d( l ) = p c l = l + 1 if( l.le.lend ) $ go to 40 go to 140 c else c c qr iteration c c look for small superdiagonal element. c 90 continue if( l.ne.lend ) then lendp1 = lend + 1 do 100 m = l, lendp1, -1 tst = abs( e( m-1 ) )**2 if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+ $ safmin )go to 110 100 continue end if c m = lend c 110 continue if( m.gt.lend ) $ e( m-1 ) = zero p = d( l ) if( m.eq.l ) $ go to 130 c c if remaining matrix is 2-by-2, use dlae2 or dlaev2 c to compute its eigensystem. c if( m.eq.l-1 ) then if( icompz.gt.0 ) then call dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) c$$$ work( m ) = c c$$$ work( n-1+m ) = s c$$$ call dlasr( 'r', 'v', 'f', n, 2, work( m ), c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz ) c c *** New starting with version 2.5 *** c tst = z(l) z(l) = c*tst - s*z(l-1) z(l-1) = s*tst + c*z(l-1) c ************************************* else call dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2 if( l.ge.lend ) $ go to 90 go to 140 end if c if( jtot.eq.nmaxit ) $ go to 140 jtot = jtot + 1 c c form shift. c g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = dlapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) c s = one c = one p = zero c c inner loop c lm1 = l - 1 do 120 i = m, lm1 f = s*e( i ) b = c*e( i ) call dlartg( g, f, c, s, r ) if( i.ne.m ) $ e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b c c if eigenvectors are desired, then save rotations. c if( icompz.gt.0 ) then work( i ) = c work( n-1+i ) = s end if c 120 continue c c if eigenvectors are desired, then apply saved rotations. c if( icompz.gt.0 ) then mm = l - m + 1 c$$$ call dlasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ), c$$$ $ z( 1, m ), ldz ) c c *** New starting with version 2.5 *** c call dlasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ), & z( m ), 1 ) c ************************************* end if c d( l ) = d( l ) - p e( lm1 ) = g go to 90 c c eigenvalue found. c 130 continue d( l ) = p c l = l - 1 if( l.ge.lend ) $ go to 90 go to 140 c end if c c undo scaling if necessary c 140 continue if( iscale.eq.1 ) then call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, $ d( lsv ), n, info ) call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ), $ n, info ) else if( iscale.eq.2 ) then call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, $ d( lsv ), n, info ) call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ), $ n, info ) end if c c check for no convergence to an eigenvalue after a total c of n*maxit iterations. c if( jtot.lt.nmaxit ) $ go to 10 do 150 i = 1, n - 1 if( e( i ).ne.zero ) $ info = info + 1 150 continue go to 190 c c order eigenvalues and eigenvectors. c 160 continue if( icompz.eq.0 ) then c c use quick sort c call dlasrt( 'i', n, d, info ) c else c c use selection sort to minimize swaps of eigenvectors c do 180 ii = 2, n i = ii - 1 k = i p = d( i ) do 170 j = ii, n if( d( j ).lt.p ) then k = j p = d( j ) end if 170 continue if( k.ne.i ) then d( k ) = d( i ) d( i ) = p c$$$ call dswap( n, z( 1, i ), 1, z( 1, k ), 1 ) c *** New starting with version 2.5 *** c p = z(k) z(k) = z(i) z(i) = p c ************************************* end if 180 continue end if c 190 continue return c c %---------------% c | End of dstqrb | c %---------------% c end arpack-ng-3.3.0/SRC/sgetv0.f000066400000000000000000000314661260666001200153770ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: sgetv0 c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call sgetv0 c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, IERR ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to sgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that sgetv0 is called. c It should be set to 1 on the initial call to sgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Real N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Real scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Real work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine for vector output. c slarnv LAPACK routine for generating a random vector. c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: getv0.F SID: 2.7 DATE OF SID: 04/07/99 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine sgetv0 & ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & resid(n), v(ldv,j), workd(2*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Real & rnorm0 save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external slarnv, svout, scopy, sgemv, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, snrm2 external sdot, snrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call slarnv (idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call scopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %-----------------------------------------% c | Back from computing OP*(initial-vector) | c %-----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c if (bmat .eq. 'G') then call arscnd (t3) tmvopx = tmvopx + (t3 - t2) end if c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then rnorm0 = sdot (n, resid, 1, workd, 1) rnorm0 = sqrt(abs(rnorm0)) else if (bmat .eq. 'I') then rnorm0 = snrm2(n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call sgemv ('T', n, j-1, one, v, ldv, workd, 1, & zero, workd(n+1), 1) call sgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = snrm2(n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call svout (logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call svout (logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 5) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = zero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call svout (logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 3) then call svout (logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %---------------% c | End of sgetv0 | c %---------------% c end arpack-ng-3.3.0/SRC/snaitr.f000066400000000000000000000734671260666001200154760ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: snaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in snaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call snaitr c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recompute in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See snaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c sgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c slabad LAPACK routine that computes machine constants. c slamch LAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c slanhs LAPACK routine that computes various norms of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: naitr.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in snaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine snaitr & (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Real & betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl, & wnorm save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, sgetv0, slabad, & svout, smout, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, snrm2, slanhs, slamch external sdot, snrm2, slanhs, slamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------% c unfl = slamch( 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = slamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | sgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call ivout (logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call svout (logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determing whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = zero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call sgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. unfl) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then wnorm = sdot (n, resid, 1, workd(ipj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = snrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = betaj c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd(ipj), 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = snrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call svout (logfil, 2, xtemp, ndigit, & '_naitr: re-orthonalization; wnorm and rnorm are') call svout (logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) call saxpy (j, one, workd(irj), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = sdot (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = snrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call svout (logfil, 2, xtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tnaitr = tnaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', k+np, h, ldh, workd(n+1) ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call smout (logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of snaitr | c %---------------% c end arpack-ng-3.3.0/SRC/snapps.f000066400000000000000000000555151260666001200154740ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: snapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge chage sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call snapps c ( N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. KEV is only c updated on ouput when fewer than NP shifts are applied in c order to keep the conjugate pair together. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFTR, Real array of length NP. (INPUT) c SHIFTI Real and imaginary part of the shifts to be applied. c Upon, entry to snapps, the shifts must be sorted so that the c conjugate pairs are in consecutive locations. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenber matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices. c svout ARPACK utility routine that prints vectors. c slabad LAPACK routine that computes machine constants. c slacpy LAPACK matrix copy routine. c slamch LAPACK routine that determines machine constants. c slanhs LAPACK routine that computes various norms of a matrix. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slarf LAPACK routine that applies Householder reflection to c a matrix. c slarfg LAPACK Householder reflection construction routine. c slartg LAPACK Givens rotation construction routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another . c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: napps.F SID: 2.4 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine slahqr (QR algorithm c for upper Hessenberg matrices ) is used. c The subdiagonals of H are enforced to be non-negative. c c\EndLib c c----------------------------------------------------------------------- c subroutine snapps & ( n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,kev+np), resid(n), shifti(np), shiftr(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr logical cconj, first Real & c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai, & sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slarfg, slarf, & slaset, slabad, arscnd, slartg c c %--------------------% c | External Functions | c %--------------------% c Real & slamch, slanhs, slapy2 external slamch, slanhs, slapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, max, min c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine slahqr | c %-----------------------------------------------% c unfl = slamch( 'safe minimum' ) ovfl = one / unfl call slabad( unfl, ovfl ) ulp = slamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mnapps kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c cconj = .false. do 110 jj = 1, np sigmar = shiftr(jj) sigmai = shifti(jj) c if (msglvl .gt. 2 ) then call ivout (logfil, 1, jj, ndigit, & '_napps: shift number.') call svout (logfil, 1, sigmar, ndigit, & '_napps: The real part of the shift ') call svout (logfil, 1, sigmai, ndigit, & '_napps: The imaginary part of the shift ') end if c c %-------------------------------------------------% c | The following set of conditionals is necessary | c | in order that complex conjugate pairs of shifts | c | are applied together or not at all. | c %-------------------------------------------------% c if ( cconj ) then c c %-----------------------------------------% c | cconj = .true. means the previous shift | c | had non-zero imaginary part. | c %-----------------------------------------% c cconj = .false. go to 110 else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then c c %------------------------------------% c | Start of a complex conjugate pair. | c %------------------------------------% c cconj = .true. else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then c c %----------------------------------------------% c | The last shift has a nonzero imaginary part. | c | Don't apply it; thus the order of the | c | compressed H is order KEV+1 since only np-1 | c | were applied. | c %----------------------------------------------% c kev = kev + 1 go to 110 end if istart = 1 20 continue c c %--------------------------------------------------% c | if sigmai = 0 then | c | Apply the jj-th shift ... | c | else | c | Apply the jj-th and (jj+1)-th together ... | c | (Note that jj < np at this point in the code) | c | end | c | to the current block of H. The next do loop | c | determines the current block ; | c %--------------------------------------------------% c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %----------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kplusp-jj+1, h, ldh, workl ) if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call svout (logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, istart, ndigit, & '_napps: Start of current block ') call ivout (logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c %------------------------------------------------% c if ( istart .eq. iend ) go to 100 c c %------------------------------------------------------% c | If istart + 1 = iend then no reason to apply a | c | complex conjugate pair of shifts on a 2 by 2 matrix. | c %------------------------------------------------------% c if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero ) & go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) if ( abs( sigmai ) .le. zero ) then c c %---------------------------------------------% c | Real-valued shift ==> apply single shift QR | c %---------------------------------------------% c f = h11 - sigmar g = h21 c do 80 i = istart, iend-1 c c %-----------------------------------------------------% c | Contruct the plane rotation G to zero out the bulge | c %-----------------------------------------------------% c call slartg (f, g, c, s, r) if (i .gt. istart) then c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -s*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + s*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 70 j = 1, min( i+jj, kplusp ) t = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-----------------------------------% c | Finished applying the real shift. | c %-----------------------------------% c else c c %----------------------------------------------------% c | Complex conjugate shifts ==> apply double shift QR | c %----------------------------------------------------% c h12 = h(istart,istart+1) h22 = h(istart+1,istart+1) h32 = h(istart+2,istart+1) c c %---------------------------------------------------------% c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) | c %---------------------------------------------------------% c s = 2.0*sigmar t = slapy2 ( sigmar, sigmai ) u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12 u(2) = h11 + h22 - s u(3) = h32 c do 90 i = istart, iend-1 c nr = min ( 3, iend-i+1 ) c c %-----------------------------------------------------% c | Construct Householder reflector G to zero out u(1). | c | G is of the form I - tau*( 1 u )' * ( 1 u' ). | c %-----------------------------------------------------% c call slarfg ( nr, u(1), u(2), 1, tau ) c if (i .gt. istart) then h(i,i-1) = u(1) h(i+1,i-1) = zero if (i .lt. iend-1) h(i+2,i-1) = zero end if u(1) = one c c %--------------------------------------% c | Apply the reflector to the left of H | c %--------------------------------------% c call slarf ('Left', nr, kplusp-i+1, u, 1, tau, & h(i,i), ldh, workl) c c %---------------------------------------% c | Apply the reflector to the right of H | c %---------------------------------------% c ir = min ( i+3, iend ) call slarf ('Right', ir, nr, u, 1, tau, & h(1,i), ldh, workl) c c %-----------------------------------------------------% c | Accumulate the reflector in the matrix Q; Q <- Q*G | c %-----------------------------------------------------% c call slarf ('Right', kplusp, nr, u, 1, tau, & q(1,i), ldq, workl) c c %----------------------------% c | Prepare for next reflector | c %----------------------------% c if (i .lt. iend-1) then u(1) = h(i+1,i) u(2) = h(i+2,i) if (i .lt. iend-2) u(3) = h(i+3,i) end if c 90 continue c c %--------------------------------------------% c | Finished applying a complex pair of shifts | c | to the current block | c %--------------------------------------------% c end if c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %--------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that H will have non negative sub diagonals | c %--------------------------------------------------% c do 120 j=1,kev if ( h(j+1,j) .lt. zero ) then call sscal( kplusp-j+1, -one, h(j+1,j), ldh ) call sscal( min(j+2, kplusp), -one, h(1,j+1), 1 ) call sscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine slahqr | c %--------------------------------------------% c tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) ) if( tst1.eq.zero ) & tst1 = slanhs( '1', kev, h, ldh, workl ) if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call sgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if (h(kev+1,kev) .gt. zero) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kplusp}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,kev) .gt. zero) & call saxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call svout (logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call svout (logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call ivout (logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call smout (logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tnapps = tnapps + (t1 - t0) c return c c %---------------% c | End of snapps | c %---------------% c end arpack-ng-3.3.0/SRC/snaup2.f000066400000000000000000000756561260666001200154100ustar00rootroot00000000000000c\BeginDoc c c\Name: snaup2 c c\Description: c Intermediate level interface called by snaupd. c c\Usage: c call snaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in snaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in snaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV for two reasons. The first, is c to keep complex conjugate pairs of "wanted" Ritz values c together. The second, is that a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length NEV+NP. (OUTPUT) c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp. c imaginary) part of the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c On exit, the last 3*(NEV+NP) locations of WORKL contain c the Ritz values (real,imaginary) and associated Ritz c estimates of the current Hessenberg matrix. They are c listed in the same order as returned from sneigh. c c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in DNAUPD. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c sgetv0 ARPACK initial vector generation routine. c snaitr ARPACK Arnoldi factorization routine. c snapps ARPACK application of implicit shifts routine. c snconv ARPACK convergence of Ritz values routine. c sneigh ARPACK compute Ritz values and error bounds routine. c sngets ARPACK reorder Ritz values and error bounds routine. c ssortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naup2.F SID: 2.8 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine snaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ipntr, workd, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Real & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n), & ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0 , zero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm , getv0, initv, update, ushift integer ierr , iter , j , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, numcnv Real & rnorm , temp , eps23 save cnorm , getv0, initv, update, ushift, & rnorm , iter , eps23, kplusp, msglvl, nconv , & nevbef, nev0 , np0 , numcnv c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(4) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sgetv0, snaitr, snconv, sneigh, & sngets, snapps, svout , ivout , arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, snrm2, slapy2, slamch external sdot, snrm2, slapy2, slamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min, max, abs, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mnaup2 c c %-------------------------------------% c | Get the machine dependent constant. | c %-------------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0 ) c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call sgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call snaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine snapps. | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call ivout (logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call snaitr (ido , bmat, n , nev, np , mode , resid, & rnorm, v , ldv, h , ldh, ipntr, workd, & info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call svout (logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call sneigh (rnorm, kplusp, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from sneigh. | c %----------------------------------------------------% c call scopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1) call scopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZR, | c | RITZI and BOUNDS respectively. The variables NEV | c | and NP may be updated if the NEV-th wanted Ritz | c | value has a non zero imaginary part. In this case | c | NEV is increased by one and NP decreased by one. | c | NOTE: The last two arguments of sngets are no | c | longer used as of version 2.1. | c %---------------------------------------------------% c nev = nev0 np = np0 numcnv = nev call sngets (ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) if (nev .eq. nev0+1) numcnv = nev0+1 c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(2*np+1), 1) call snconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1), & tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = numcnv kp(4) = nconv call ivout (logfil, 4, kp, ndigit, & '_naup2: NEV, NP, NUMCNV, NCONV are') call svout (logfil, kplusp, ritzr, ndigit, & '_naup2: Real part of the eigenvalues of H') call svout (logfil, kplusp, ritzi, ndigit, & '_naup2: Imaginary part of the eigenvalues of H') call svout (logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. numcnv) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call svout(logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Real part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Imag part of the eig computed by _neigh:') call svout(logfil, kplusp, workl(kplusp**2+kplusp*2+1), & ndigit, & '_naup2: Ritz eistmates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to _neupd if needed | c %------------------------------------------% h(3,1) = rnorm c c %----------------------------------------------% c | To be consistent with sngets, we first do a | c | pre-processing sort in order to keep complex | c | conjugate pairs together. This is similar | c | to the pre-processing sort used in sngets | c | except that the sort is done in the opposite | c | order. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SR' if (which .eq. 'SM') wprime = 'LR' if (which .eq. 'LR') wprime = 'SM' if (which .eq. 'SR') wprime = 'LM' if (which .eq. 'LI') wprime = 'SM' if (which .eq. 'SI') wprime = 'LM' c call ssortc (wprime, .true., kplusp, ritzr, ritzi, bounds) c c %----------------------------------------------% c | Now sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritzr, ritzi and bounds, and the most | c | desired one appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call ssortc(wprime, .true., kplusp, ritzr, ritzi, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, numcnv temp = max(eps23,slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LR' call ssortc(wprime, .true., numcnv, bounds, ritzr, ritzi) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, numcnv temp = max(eps23, slapy2(ritzr(j), & ritzi(j))) bounds(j) = bounds(j)*temp 40 continue c c %------------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritzr, ritzi and bound. | c %------------------------------------------------% c call ssortc(which, .true., nconv, ritzr, ritzi, bounds) c if (msglvl .gt. 1) then call svout (logfil, kplusp, ritzr, ndigit, & '_naup2: Sorted real part of the eigenvalues') call svout (logfil, kplusp, ritzi, ndigit, & '_naup2: Sorted imaginary part of the eigenvalues') call svout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. numcnv) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if c %---- Scipy fix ------------------------------------------------ c | We must keep nev below this value, as otherwise we can get c | np == 0 (note that sngets below can bump nev by 1). If np == 0, c | the next call to `snaitr` will write out-of-bounds. c | if (nev .gt. kplusp - 2) then nev = kplusp - 2 end if c | c %---- Scipy fix end -------------------------------------------- c np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call sngets (ishift, which, nev, np, ritzr, ritzi, & bounds, workl, workl(np+1)) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call svout (logfil, nev, ritzr(np+1), ndigit, & '_naup2: "wanted" Ritz values -- real part') call svout (logfil, nev, ritzi(np+1), ndigit, & '_naup2: "wanted" Ritz values -- imag part') call svout (logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: reverse comminucation to | c | compute the shifts. They are returned in the first | c | 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:2*NP) | c %------------------------------------% c ushift = .false. c if ( ishift .eq. 0 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZR, RITZI to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call scopy (np, workl, 1, ritzr, 1) call scopy (np, workl(np+1), 1, ritzi, 1) end if c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call svout (logfil, np, ritzr, ndigit, & '_naup2: Real part of the shifts') call svout (logfil, np, ritzi, ndigit, & '_naup2: Imaginary part of the shifts') if ( ishift .eq. 1 ) & call svout (logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call snapps (n, nev, np, ritzr, ritzi, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to snaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = snrm2(n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call svout (logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call smout (logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = numcnv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tnaup2 = t1 - t0 c 9000 continue c c %---------------% c | End of snaup2 | c %---------------% c return end arpack-ng-3.3.0/SRC/snaupd.f000066400000000000000000000717761260666001200154710ustar00rootroot00000000000000c\BeginDoc c c\Name: snaupd c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This subroutine computes approximations to a few eigenpairs c of a linear operator "OP" with respect to a semi-inner product defined by c a symmetric positive semi-definite real matrix B. B may be the identity c matrix. NOTE: If the linear operator "OP" is real and symmetric c with respect to the real positive semi-definite symmetric matrix B, c i.e. B*OP = (OP`)*B, then subroutine ssaupd should be used instead. c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c snaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ]. c Note: If sigma is real, i.e. imaginary part of sigma is zero; c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M c amu == 1/(lambda-sigma). c c Mode 4: A*x = lambda*M*x, M symmetric semi-definite c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M. c ===> shift-and-invert mode (in real arithmetic) c If OP*x = amu*x, then c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ]. c c Both mode 3 and 4 give the same enhancement to eigenvalues close to c the (complex) shift sigma. However, as lambda goes to infinity, c the operator OP in mode 4 dampens the eigenvalues more strongly than c does OP defined in mode 3. c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call snaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to snaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c snaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3 and 4, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) real and imaginary parts c of the shifts where INPTR(14) is the pointer c into WORKL for placing the shifts. See Remark c 5 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 2 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz c values are kept together. (See remark 4 below) c c V Real array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The real and imaginary c parts of the NCV eigenvalues of the Hessenberg c matrix H are returned in the part of the WORKL c array corresponding to RITZR and RITZI. See remark c 5 below. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of approximate Schur c vectors associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4; See under \Description of snaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), snaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 5 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix c H in WORKL. c IPNTR(6): pointer to the real part of the ritz value array c RITZR in WORKL. c IPNTR(7): pointer to the imaginary part of the ritz value array c RITZI in WORKL. c IPNTR(8): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZR and RITZI in WORKL. c c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by sneupd. See Remark 2 below. c c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c sneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace c associated with the converged Ritz values is desired, see remark c 2 below, subroutine sneupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 6*NCV. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when c Mode = 3 and 4. After convergence, approximate eigenvalues of the c original problem may be obtained with the ARPACK subroutine sneupd. c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call sneupd immediately following c completion of snaupd. This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2. c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) real and imaginary parts of the shifts in locations c real part imaginary part c ----------------------- -------------- c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP) c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1) c . . c . . c . . c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1). c c Only complex conjugate pairs of shifts may be applied and the pairs c must be placed in consecutive locations. The real part of the c eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered c according to the order defined by WHICH. The complex conjugate c pairs are kept together and the associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Real resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Real resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c snaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version '1.1' c c\SCCS Information: @(#) c FILE: naupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine snaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0 , zero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritzi, ritzr, j save bounds, ih, iq, ishift, iupd, iw, ldh, ldq, & levec, mode, msglvl, mxiter, nb, nev0, next, & np, ritzi, ritzr c c %----------------------% c | External Subroutines | c %----------------------% c external snaup2, svout, ivout, arscnd, sstatn c c %--------------------% c | External Functions | c %--------------------% c Real & slamch external slamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstatn call arscnd (t0) msglvl = mnaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 4) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = slamch('EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 6*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace | c | The final workspace is needed by subroutine sneigh called | c | by snaup2. Subroutine sneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritzr = ih + ldh*ncv ritzi = ritzr + ncv bounds = ritzi + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritzr ipntr(7) = ritzi ipntr(8) = bounds ipntr(14) = iw c end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call snaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr), & workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within snaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call svout (logfil, np, workl(ritzr), ndigit, & '_naupd: Real part of the final Ritz values') call svout (logfil, np, workl(ritzi), ndigit, & '_naupd: Imaginary part of the final Ritz values') call svout (logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tnaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref, & tgetv0, tneigh, tngets, tnapps, tnconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Nonsymmetric implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.4' , 21x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if c 9000 continue c return c c %---------------% c | End of snaupd | c %---------------% c end arpack-ng-3.3.0/SRC/snconv.f000066400000000000000000000076411260666001200154730ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: snconv c c\Description: c Convergence testing for the nonsymmetric Arnoldi eigenvalue routine. c c\Usage: c call snconv c ( N, RITZR, RITZI, BOUNDS, TOL, NCONV ) c c\Arguments c N Integer. (INPUT) c Number of Ritz values to check for convergence. c c RITZR, Real arrays of length N. (INPUT) c RITZI Real and imaginary parts of the Ritz values to be checked c for convergence. c BOUNDS Real array of length N. (INPUT) c Ritz estimates for the Ritz values in RITZR and RITZI. c c TOL Real scalar. (INPUT) c Desired backward error for a Ritz value to be considered c "converged". c c NCONV Integer scalar. (OUTPUT) c Number of "converged" Ritz values. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c arscnd ARPACK utility routine for timing. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: nconv.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine snconv (n, ritzr, ritzi, bounds, tol, nconv) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer n, nconv Real & tol c c %-----------------% c | Array Arguments | c %-----------------% Real & ritzr(n), ritzi(n), bounds(n) c c %---------------% c | Local Scalars | c %---------------% c integer i Real & temp, eps23 c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, slamch external slapy2, slamch c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------------------% c | Convergence test: unlike in the symmetric code, I am not | c | using things like refined error bounds and gap condition | c | because I don't know the exact equivalent concept. | c | | c | Instead the i-th Ritz value is considered "converged" when: | c | | c | bounds(i) .le. ( TOL * | ritz | ) | c | | c | for some appropriate choice of norm. | c %-------------------------------------------------------------% c call arscnd (t0) c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0) c nconv = 0 do 20 i = 1, n temp = max( eps23, slapy2( ritzr(i), ritzi(i) ) ) if (bounds(i) .le. tol*temp) nconv = nconv + 1 20 continue c call arscnd (t1) tnconv = tnconv + (t1 - t0) c return c c %---------------% c | End of snconv | c %---------------% c end arpack-ng-3.3.0/SRC/sneigh.f000066400000000000000000000242021260666001200154320ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: sneigh c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call sneigh c ( RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR ) c c\Arguments c RNORM Real scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Real N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZR, Real arrays of length N. (OUTPUT) c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real c (respectively imaginary) parts of the eigenvalues of H. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues RITZR and RITZI. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZR and RITZI. c c Q Real N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c IERR Integer. (OUTPUT) c Error exit flag from slahqr or strevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c slahqr ARPACK routine to compute the real Schur form of an c upper Hessenberg matrix and last row of the Schur vectors. c arscnd ARPACK utility routine for timing. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c slacpy LAPACK matrix copy routine. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form c sgemv Level 2 BLAS routine for matrix vector multiplication. c scopy Level 1 BLAS that copies one vector to another . c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: neigh.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine sneigh (rnorm, n, h, ldh, ritzr, ritzi, bounds, & q, ldq, workl, ierr) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n), & workl(n*(n+3)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer i, iconj, msglvl Real & temp, vl(1) c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, slacpy, slahqr, strevc, svout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2 external slapy2, snrm2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mneigh c if (msglvl .gt. 2) then call smout (logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %-----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | slahqr returns the full Schur form of H in WORKL(1:N**2) | c | and the last components of the Schur vectors in BOUNDS. | c %-----------------------------------------------------------% c call slacpy ('All', n, n, h, ldh, workl, n) do 5 j = 1, n-1 bounds(j) = zero 5 continue bounds(n) = one call slahqr(.true., .true., n, 1, n, workl, n, ritzr, ritzi, 1, 1, & bounds, 1, ierr) if (ierr .ne. 0) go to 9000 c if (msglvl .gt. 1) then call svout (logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %-----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the last components of the Schur vectors to get | c | the last components of the corresponding eigenvectors. | c | Remember that if the i-th and (i+1)-st eigenvalues are | c | complex conjugate pairs, then the real & imaginary part | c | of the eigenvector components are split across adjacent | c | columns of Q. | c %-----------------------------------------------------------% c call strevc ('R', 'A', select, n, workl, n, vl, n, q, ldq, & n, n, workl(n*n+1), ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c iconj = 0 do 10 i=1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c temp = snrm2( n, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i), 1 ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2( snrm2( n, q(1,i), 1 ), & snrm2( n, q(1,i+1), 1 ) ) call sscal ( n, one / temp, q(1,i), 1 ) call sscal ( n, one / temp, q(1,i+1), 1 ) iconj = 1 else iconj = 0 end if end if 10 continue c call sgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1) c if (msglvl .gt. 1) then call svout (logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c iconj = 0 do 20 i = 1, n if ( abs( ritzi(i) ) .le. zero ) then c c %----------------------% c | Real eigenvalue case | c %----------------------% c bounds(i) = rnorm * abs( workl(i) ) else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we need to take the magnitude | c | of the last components of the two vectors | c %-------------------------------------------% c if (iconj .eq. 0) then bounds(i) = rnorm * slapy2( workl(i), workl(i+1) ) bounds(i+1) = bounds(i) iconj = 1 else iconj = 0 end if end if 20 continue c if (msglvl .gt. 2) then call svout (logfil, n, ritzr, ndigit, & '_neigh: Real part of the eigenvalues of H') call svout (logfil, n, ritzi, ndigit, & '_neigh: Imaginary part of the eigenvalues of H') call svout (logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd (t1) tneigh = tneigh + (t1 - t0) c 9000 continue return c c %---------------% c | End of sneigh | c %---------------% c end arpack-ng-3.3.0/SRC/sneupd.f000066400000000000000000001261441260666001200154630ustar00rootroot00000000000000c\BeginDoc c c\Name: sneupd c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to SNAUPD. SNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c See documentation in the header of the subroutine SNAUPD for c definition of OP as well as other terms and the relation of computed c Ritz values and Ritz vectors of OP with respect to the given problem c A*z = lambda*B*z. For a brief description, see definitions of c IPARAM(7), MODE and WHICH in the documentation of SNAUPD. c c\Usage: c call sneupd c ( RVEC, HOWMNY, SELECT, DR, DI, Z, LDZ, SIGMAR, SIGMAI, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, c LWORKL, INFO ) c c\Arguments: c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute the Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value (DR(j), DI(j)), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT is used as internal workspace. c c DR Real array of dimension NEV+1. (OUTPUT) c If IPARAM(7) = 1,2 or 3 and SIGMAI=0.0 then on exit: DR contains c the real part of the Ritz approximations to the eigenvalues of c A*z = lambda*B*z. c If IPARAM(7) = 3, 4 and SIGMAI is not equal to zero, then on exit: c DR contains the real part of the Ritz values of OP computed by c SNAUPD. A further computation must be performed by the user c to transform the Ritz values computed for OP by SNAUPD to those c of the original system A*z = lambda*B*z. See remark 3 below. c c DI Real array of dimension NEV+1. (OUTPUT) c On exit, DI contains the imaginary part of the Ritz value c approximations to the eigenvalues of A*z = lambda*B*z associated c with DR. c c NOTE: When Ritz values are complex, they will come in complex c conjugate pairs. If eigenvectors are requested, the c corresponding Ritz vectors will also come in conjugate c pairs and the real and imaginary parts of these are c represented in two consecutive columns of the array Z c (see below). c c Z Real N by NEV+1 array if RVEC = .TRUE. and HOWMNY = 'A'. (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represent approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c The complex Ritz vector associated with the Ritz value c with positive imaginary part is stored in two consecutive c columns. The first column holds the real part of the Ritz c vector and the second column holds the imaginary part. The c Ritz vector associated with the Ritz value with negative c imaginary part is simply the complex conjugate of the Ritz vector c associated with the positive imaginary part. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is not referenced. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by SNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ >= max( 1, N ). In any case, LDZ >= 1. c c SIGMAR Real (INPUT) c If IPARAM(7) = 3 or 4, represents the real part of the shift. c Not referenced if IPARAM(7) = 1 or 2. c c SIGMAI Real (INPUT) c If IPARAM(7) = 3 or 4, represents the imaginary part of the shift. c Not referenced if IPARAM(7) = 1 or 2. See remark 3 below. c c WORKEV Real work array of dimension 3*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to SNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to SNEUPD following the last call c to SNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to SNAUPD and the call to SNEUPD. c c Three of these parameters (V, WORKL, INFO) are also output parameters: c c V Real N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by SNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. See Remark 2 below. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+3*ncv) contains information obtained in c snaupd. They are not changed by sneupd. c WORKL(ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) holds the c real and imaginary part of the untransformed Ritz values, c the upper quasi-triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by sneupd. c ------------------------------------------------------------- c IPNTR(9): pointer to the real part of the NCV RITZ values of the c original system. c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of c the original system. c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c sneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine slahqr c could not be reordered by LAPACK routine strsen. c Re-enter subroutine sneupd with IPARAM(5)=NCV and c increase the size of the arrays DR and DI to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from calculation of a real Schur form. c Informational error from LAPACK routine slahqr. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine strevc. c = -10: IPARAM(7) must be 1,2,3,4. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: SNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: DNEUPD got a different count of the number of converged c Ritz values than DNAUPD got. This indicates the user c probably made an error in passing data from DNAUPD to c DNEUPD or that the data was modified before entering c DNEUPD c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for c Real Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c ivout ARPACK utility routine that prints integers. c smout ARPACK utility routine that prints matrices c svout ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c slahqr LAPACK routine to compute the real Schur form of an c upper Hessenberg matrix. c slamch LAPACK routine that determines machine constants. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slaset LAPACK matrix initialization routine. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c strevc LAPACK routine to compute the eigenvectors of a matrix c in upper quasi-triangular form. c strsen LAPACK routine that re-orders the Schur form. c strmm Level 3 BLAS matrix times an upper triangular matrix. c sger Level 2 BLAS rank one update to a matrix. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c Let trans(X) denote the transpose of X. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .TRUE. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c trans(V(:,1:IPARAM(5))) * V(:,1:IPARAM(5)) = I are approximately c satisfied. Here T is the leading submatrix of order IPARAM(5) of the c real upper quasi-triangular matrix stored workl(ipntr(12)). That is, c T is block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; c each 2-by-2 diagonal block has its diagonal elements equal and its c off-diagonal elements of opposite sign. Corresponding to each 2-by-2 c diagonal block is a complex conjugate pair of Ritz values. The real c Ritz values are stored on the diagonal of T. c c 3. If IPARAM(7) = 3 or 4 and SIGMAI is not equal zero, then the user must c form the IPARAM(5) Rayleigh quotients in order to transform the Ritz c values computed by SNAUPD for OP to those of A*z = lambda*B*z. c Set RVEC = .true. and HOWMNY = 'A', and c compute c trans(Z(:,I)) * A * Z(:,I) if DI(I) = 0. c If DI(I) is not equal to zero and DI(I+1) = - D(I), c then the desired real and imaginary parts of the Ritz value are c trans(Z(:,I)) * A * Z(:,I) + trans(Z(:,I+1)) * A * Z(:,I+1), c trans(Z(:,I)) * A * Z(:,I+1) - trans(Z(:,I+1)) * A * Z(:,I), c respectively. c Another possibility is to set RVEC = .true. and HOWMNY = 'P' and c compute trans(V(:,1:IPARAM(5))) * A * V(:,1:IPARAM(5)) and then an upper c quasi-triangular matrix of order IPARAM(5) is computed. See remark c 2 above. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neupd.F SID: 2.7 DATE OF SID: 09/20/00 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine sneupd(rvec , howmny, select, dr , di, & z , ldz , sigmar, sigmai, workev, & bmat , n , which , nev , tol, & resid, ncv , v , ldv , iparam, & ipntr, workd , workl , lworkl, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigmar, sigmai, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Real & dr(nev+1) , di(nev+1), resid(n) , & v(ldv,ncv) , z(ldz,*) , workd(3*n), & workl(lworkl), workev(3*ncv) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0 , zero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds , & iheigr, iheigi, iconj , nconv , & invsub, iuptri, iwev , iwork(1), & j , k , ldh , ldq , & mode , msglvl, outncv, ritzr , & ritzi , wri , wrr , irr , & iri , ibd , ishift, numcnv , & np , jj , nconv2 logical reord Real & conds , rnorm, sep , temp, & vl(1,1), temp1, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, & slahqr, slaset, smout , sorm2r, & strevc, strmm , strsen, sscal , & svout , ivout c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2, snrm2, slamch, sdot external slapy2, snrm2, slamch, sdot c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs, min, sqrt c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mneupd mode = iparam(7) nconv = iparam(5) info = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0 ) c c %--------------% c | Quick return | c %--------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 6*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 .and. sigmai .eq. zero) then type = 'SHIFTI' else if (mode .eq. 3 ) then type = 'REALPT' else if (mode .eq. 4 ) then type = 'IMAGPT' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary | c | parts of ritz values | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by SNEUPD. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | real part of the Ritz values. | c | workl(ncv*ncv+4*ncv+1:ncv*ncv+5*ncv) := The untransformed | c | imaginary part of the Ritz values. | c | workl(ncv*ncv+5*ncv+1:ncv*ncv+6*ncv) := The untransformed | c | error bounds of the Ritz values | c | workl(ncv*ncv+6*ncv+1:2*ncv*ncv+6*ncv) := Holds the upper | c | quasi-triangular matrix for H | c | workl(2*ncv*ncv+6*ncv+1: 3*ncv*ncv+6*ncv) := Holds the | c | associated matrix representation of the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 6 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritzr = ipntr(6) ritzi = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheigr = bounds + ldh iheigi = iheigr + ldh ihbds = iheigi + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheigr ipntr(10) = iheigi ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wrr = 1 wri = ncv + 1 iwev = wri + ncv c c %-----------------------------------------% c | irr points to the REAL part of the Ritz | c | values computed by _neigh before | c | exiting _naup2. | c | iri points to the IMAGINARY part of the | c | Ritz values computed by _neigh | c | before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irr = ipntr(14)+ncv*ncv iri = irr+ncv ibd = iri+ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call svout(logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values passed in from _NAUPD.') call svout(logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values passed in from _NAUPD.') call svout(logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call sngets(ishift , which , nev , & np , workl(irr), workl(iri), & workl(bounds), workl , workl(np+1)) c if (msglvl .gt. 2) then call svout(logfil, ncv, workl(irr), ndigit, & '_neupd: Real part of Ritz values after calling _NGETS.') call svout(logfil, ncv, workl(iri), ndigit, & '_neupd: Imag part of Ritz values after calling _NGETS.') call svout(logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, & slapy2( workl(irr+ncv-j), workl(iri+ncv-j) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine slahqr to compute the real Schur form | c | of the upper Hessenberg matrix returned by SNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call slaset('All', ncv, ncv, & zero , one, workl(invsub), & ldq) call slahqr(.true., .true. , ncv, & 1 , ncv , workl(iuptri), & ldh , workl(iheigr), workl(iheigi), & 1 , ncv , workl(invsub), & ldq , ierr) call scopy(ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call svout(logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H') call svout(logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imaginary part of the Eigenvalues of H') call svout(logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call smout(logfil , ncv, ncv , & workl(iuptri), ldh, ndigit, & '_neupd: The upper quasi-triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------------% c | Reorder the computed upper quasi-triangular matrix. | c %-----------------------------------------------------% c call strsen('None' , 'V' , & select , ncv , & workl(iuptri), ldh , & workl(invsub), ldq , & workl(iheigr), workl(iheigi), & nconv2 , conds , & sep , workl(ihbds) , & ncv , iwork , & 1 , ierr) c if (nconv2 .lt. nconv) then nconv = nconv2 end if if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call svout(logfil, ncv, workl(iheigr), ndigit, & '_neupd: Real part of the eigenvalues of H--reordered') call svout(logfil, ncv, workl(iheigi), ndigit, & '_neupd: Imag part of the eigenvalues of H--reordered') if (msglvl .gt. 3) then call smout(logfil , ncv, ncv , & workl(iuptri), ldq, ndigit, & '_neupd: Quasi-triangular matrix after re-ordering') end if end if c end if c c %---------------------------------------% c | Copy the last row of the Schur vector | c | into workl(ihbds). This will be used | c | to compute the Ritz estimates of | c | converged Ritz values. | c %---------------------------------------% c call scopy(ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1) c c %----------------------------------------------------% c | Place the computed eigenvalues of H into DR and DI | c | if a spectral transformation was not used. | c %----------------------------------------------------% c if (type .eq. 'REGULR') then call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %---------------------------------------------------------% c | * Postmultiply V by Q using sorm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheigr) and workl(iheigi) | c | The first NCONV columns of V are now approximate Schur | c | vectors associated with the real upper quasi-triangular | c | matrix of order NCONV in workl(iuptri) | c %---------------------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr) call slacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | quasi-triangular form of workl(iuptri,ldq) | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones | c %---------------------------------------------------% c if (workl(invsub+(j-1)*ldq+j-1) .lt. zero) then call sscal(nconv, -one, workl(iuptri+j-1), ldq) call sscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call strevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | strevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; | c %------------------------------------------------% c iconj = 0 do 40 j=1, nconv c if ( workl(iheigi+j-1) .eq. zero ) then c c %----------------------% c | real eigenvalue case | c %----------------------% c temp = snrm2( ncv, workl(invsub+(j-1)*ldq), 1 ) call sscal( ncv, one / temp, & workl(invsub+(j-1)*ldq), 1 ) c else c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c | columns, we further normalize by the | c | square root of two. | c %-------------------------------------------% c if (iconj .eq. 0) then temp = slapy2(snrm2(ncv, & workl(invsub+(j-1)*ldq), & 1), & snrm2(ncv, & workl(invsub+j*ldq), & 1)) call sscal(ncv, one/temp, & workl(invsub+(j-1)*ldq), 1 ) call sscal(ncv, one/temp, & workl(invsub+j*ldq), 1 ) iconj = 1 else iconj = 0 end if c end if c 40 continue c call sgemv('T', ncv, nconv, one, workl(invsub), & ldq, workl(ihbds), 1, zero, workev, 1) c iconj = 0 do 45 j=1, nconv if (workl(iheigi+j-1) .ne. zero) then c c %-------------------------------------------% c | Complex conjugate pair case. Note that | c | since the real and imaginary part of | c | the eigenvector are stored in consecutive | c %-------------------------------------------% c if (iconj .eq. 0) then workev(j) = slapy2(workev(j), workev(j+1)) workev(j+1) = workev(j) iconj = 1 else iconj = 0 end if end if 45 continue c if (msglvl .gt. 2) then call scopy(ncv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call svout(logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call smout(logfil, ncv, ncv, workl(invsub), ldq, & ndigit, '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call scopy(nconv, workev, 1, workl(ihbds), 1) c c %---------------------------------------------------------% c | Compute the QR factorization of the eigenvector matrix | c | associated with leading portion of T in the first NCONV | c | columns of workl(invsub,ldq). | c %---------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(invsub), & ldq, workev, workev(ncv+1), & ierr) c c %----------------------------------------------% c | * Postmultiply Z by Q. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now contains the | c | Ritz vectors associated with the Ritz values | c | in workl(iheigr) and workl(iheigi). | c %----------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , z , & ldz , workd(n+1) , ierr) c call strmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) c end if c else c c %------------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed SNAUPD into DR and DI | c %------------------------------------------------------% c call scopy(nconv, workl(ritzr), 1, dr, 1) call scopy(nconv, workl(ritzi), 1, di, 1) call scopy(nconv, workl(ritzr), 1, workl(iheigr), 1) call scopy(nconv, workl(ritzi), 1, workl(iheigi), 1) call scopy(nconv, workl(bounds), 1, workl(ihbds), 1) end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (type .eq. 'SHIFTI') then c if (rvec) & call sscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = slapy2( workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(ihbds+k-1) = abs( workl(ihbds+k-1) ) & / temp / temp 50 continue c else if (type .eq. 'REALPT') then c do 60 k=1, ncv 60 continue c else if (type .eq. 'IMAGPT') then c do 70 k=1, ncv 70 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'REALPT' or 'IMAGPT' the user must from | c | Rayleigh quotients or a projection. See remark 3 above.| c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then c do 80 k=1, ncv temp = slapy2( workl(iheigr+k-1), & workl(iheigi+k-1) ) workl(iheigr+k-1) = workl(iheigr+k-1)/temp/temp & + sigmar workl(iheigi+k-1) = -workl(iheigi+k-1)/temp/temp & + sigmai 80 continue c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c else if (type .eq. 'REALPT' .or. type .eq. 'IMAGPT') then c call scopy(nconv, workl(iheigr), 1, dr, 1) call scopy(nconv, workl(iheigi), 1, di, 1) c end if c end if c if (type .eq. 'SHIFTI' .and. msglvl .gt. 1) then call svout(logfil, nconv, dr, ndigit, & '_neupd: Untransformed real part of the Ritz valuess.') call svout (logfil, nconv, di, ndigit, & '_neupd: Untransformed imag part of the Ritz valuess.') call svout(logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of untransformed Ritz values.') else if (type .eq. 'REGULR' .and. msglvl .gt. 1) then call svout(logfil, nconv, dr, ndigit, & '_neupd: Real parts of converged Ritz values.') call svout (logfil, nconv, di, ndigit, & '_neupd: Imag parts of converged Ritz values.') call svout(logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 2. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. Remember that when theta | c | has nonzero imaginary part, the corresponding | c | Ritz vector is stored across two columns of Z. | c %------------------------------------------------% c iconj = 0 do 110 j=1, nconv if (workl(iheigi+j-1) .eq. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) / & workl(iheigr+j-1) else if (iconj .eq. 0) then temp = slapy2( workl(iheigr+j-1), workl(iheigi+j-1) ) workev(j) = ( workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigr+j-1) + & workl(invsub+j*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp workev(j+1) = ( workl(invsub+j*ldq+ncv-1) * & workl(iheigr+j-1) - & workl(invsub+(j-1)*ldq+ncv-1) * & workl(iheigi+j-1) ) / temp / temp iconj = 1 else iconj = 0 end if 110 continue c c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call sger(n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %---------------% c | End of SNEUPD | c %---------------% c end arpack-ng-3.3.0/SRC/sngets.f000066400000000000000000000174541260666001200154730ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: sngets c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call sngets c ( ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest real part. c 'SR' -> want the KEV eigenvalues of smallest real part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT/OUTPUT) c INPUT: KEV+NP is the size of the matrix H. c OUTPUT: Possibly increases KEV by one to keep complex conjugate c pairs together. c c NP Integer. (INPUT/OUTPUT) c Number of implicit shifts to be computed. c OUTPUT: Possibly decreases NP by one to keep complex conjugate c pairs together. c c RITZR, Real array of length KEV+NP. (INPUT/OUTPUT) c RITZI On INPUT, RITZR and RITZI contain the real and imaginary c parts of the eigenvalues of H. c On OUTPUT, RITZR and RITZI are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. *** c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortc ARPACK sorting routine. c scopy Level 1 BLAS that copies one vector to another . c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c c\SCCS Information: @(#) c FILE: ngets.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. xxxx c c\EndLib c c----------------------------------------------------------------------- c subroutine sngets ( ishift, which, kev, np, ritzr, ritzi, bounds, & shiftr, shifti ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritzr(kev+np), ritzi(kev+np), & shiftr(1), shifti(1) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0, zero = 0.0) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, ssortc, arscnd c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mngets c c %----------------------------------------------------% c | LM, SM, LR, SR, LI, SI case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c | We first do a pre-processing sort in order to keep | c | complex conjugate pairs together | c %----------------------------------------------------% c if (which .eq. 'LM') then call ssortc ('LR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SM') then call ssortc ('SR', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LR') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SR') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'LI') then call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds) else if (which .eq. 'SI') then call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds) end if c call ssortc (which, .true., kev+np, ritzr, ritzi, bounds) c c %-------------------------------------------------------% c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) | c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero | c | Accordingly decrease NP by one. In other words keep | c | complex conjugate pairs together. | c %-------------------------------------------------------% c if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero & .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then np = np - 1 kev = kev + 1 end if c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when they shifts | c | are applied in subroutine snapps. | c | Be careful and use 'SR' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call ssortc ( 'SR', .true., np, bounds, ritzr, ritzi ) end if c call arscnd (t1) tngets = tngets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is') call ivout (logfil, 1, np, ndigit, '_ngets: NP is') call svout (logfil, kev+np, ritzr, ndigit, & '_ngets: Eigenvalues of current H matrix -- real part') call svout (logfil, kev+np, ritzi, ndigit, & '_ngets: Eigenvalues of current H matrix -- imag part') call svout (logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %---------------% c | End of sngets | c %---------------% c end arpack-ng-3.3.0/SRC/ssaitr.f000066400000000000000000000737271260666001200155020ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step symmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in ssaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call ssaitr c ( IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and does not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of matrix B that defines the c semi-inner product for the operator OP. See ssaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current order of H and the number of columns of V. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c MODE Integer. (INPUT) c Signifies which form for "OP". If MODE=2 then c a reduction in the number of B matrix vector multiplies c is possible since the B-norm of OP*x is equivalent to c the inv(B)-norm of A*x. c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Real scalar. (INPUT/OUTPUT) c On INPUT the B-norm of r_{k}. c On OUTPUT the B-norm of the updated residual r_{k+p}. c c V Real N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (K+NP) by 2 array. (INPUT/OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c with the subdiagonal in the first column starting at H(2,1) c and the main diagonal in the second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On INPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K step Arnoldi factorization. Used to save some c computation at the first step. c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated c with the K+NP step Arnoldi factorization. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of an invariant subspace of OP is found that is c less than K + NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c sgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c smout ARPACK utility routine that prints matrices. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c slascl LAPACK routine for careful scaling of a matrix. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c sscal Level 1 BLAS that scales a vector. c scopy Level 1 BLAS that copies one vector to another . c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: saitr.F SID: 2.6 DATE OF SID: 8/28/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in ssaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c alphaj <- j-th component of w_{j} c rnorm = || r_{j} || c betaj+1 = rnorm c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine ssaitr & (ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, mode, np Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & h(ldh,2), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl, & infol, jj Real & rnorm1, wnorm, safmin, temp1 save orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, & rnorm1, safmin, wnorm c c %-----------------------% c | Local Array Arguments | c %-----------------------% c Real & xtemp(2) c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, sgemv, sgetv0, svout, smout, & slascl, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, snrm2, slamch external sdot, snrm2, slamch c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then first = .false. c c %--------------------------------% c | safmin = safe minimum is such | c | that 1/sfmin does not overflow | c %--------------------------------% c safmin = slamch('safmin') end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. c c %--------------------------------% c | Pointer to the current step of | c | the factorization to build | c %--------------------------------% c j = k + 1 c c %------------------------------------------% c | Pointers used for reverse communication | c | when using WORKD. | c %------------------------------------------% c ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | sgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %------------------------------% c | Else this is the first step. | c %------------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% c 1000 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, j, ndigit, & '_saitr: generating Arnoldi vector no.') call svout (logfil, 1, rnorm, ndigit, & '_saitr: B-norm of the current residual =') end if c c %---------------------------------------------------------% c | Check for exact zero. Equivalent to determing whether a | c | j-step Arnoldi factorization is present. | c %---------------------------------------------------------% c if (rnorm .gt. zero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_saitr: ****** restart at step ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call sgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call scopy (n, resid, 1, v(1,j), 1) if (rnorm .ge. safmin) then temp1 = one / rnorm call sscal (n, temp1, v(1,j), 1) call sscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine SLASCL | c %-----------------------------------------% c call slascl ('General', i, i, rnorm, one, n, 1, & v(1,j), n, infol) call slascl ('General', i, i, rnorm, one, n, 1, & workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call scopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. | c %-----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call scopy (n, workd(irj), 1, resid, 1) c c %-------------------------------------------% c | STEP 4: Finish extending the symmetric | c | Arnoldi to length j. If MODE = 2 | c | then B*OP = B*inv(B)*A = A and | c | we don't need to compute B*OP. | c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is | c | assumed to have A*v_{j}. | c %-------------------------------------------% c if (mode .eq. 2) go to 65 call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy(n, resid, 1 , workd(ipj), 1) end if 60 continue c c %-----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. | c %-----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c 65 continue if (mode .eq. 2) then c c %----------------------------------% c | Note that the B-norm of OP*v_{j} | c | is the inv(B)-norm of A*v_{j}. | c %----------------------------------% c wnorm = sdot (n, resid, 1, workd(ivj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'G') then wnorm = sdot (n, resid, 1, workd(ipj), 1) wnorm = sqrt(abs(wnorm)) else if (bmat .eq. 'I') then wnorm = snrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c if (mode .ne. 2 ) then call sgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero, & workd(irj), 1) else if (mode .eq. 2) then call sgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero, & workd(irj), 1) end if c c %--------------------------------------% c | Orthgonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call sgemv('N', n, j, -one, v, ldv, workd(irj), 1, one, & resid, 1) c c %--------------------------------------% c | Extend H to have j rows and columns. | c %--------------------------------------% c h(j,2) = workd(irj + j - 1) if (j .eq. 1 .or. rstart) then h(j,1) = zero else h(j,1) = rnorm end if call arscnd (t4) c orth1 = .true. iter = 0 c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd(ipj), 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = snrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c %-----------------------------------------------------------% c if (rnorm .gt. 0.717*wnorm) go to 100 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then xtemp(1) = wnorm xtemp(2) = rnorm call svout (logfil, 2, xtemp, ndigit, & '_saitr: re-orthonalization ; wnorm and rnorm are') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %----------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) + | c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only | c | H(j,j) is updated. | c %----------------------------------------------% c call sgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) c if (j .eq. 1 .or. rstart) h(j,1) = zero h(j,2) = h(j,2) + workd(irj + j - 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then rnorm1 = sdot (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt(abs(rnorm1)) else if (bmat .eq. 'I') then rnorm1 = snrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_saitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then xtemp(1) = rnorm xtemp(2) = rnorm1 call svout (logfil, 2, xtemp, ndigit, & '_saitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if (rnorm1 .gt. 0.717*rnorm) then c c %--------------------------------% c | No need for further refinement | c %--------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = zero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %----------------------------------------------------------% c | Make sure the last off-diagonal element is non negative | c | If not perform a similarity transformation on H(1:j,1:j) | c | and scale v(:,j) by -1. | c %----------------------------------------------------------% c if (h(j,1) .lt. zero) then h(j,1) = -h(j,1) if ( j .lt. k+np) then call sscal(n, -one, v(1,j+1), 1) else call sscal(n, -one, resid, 1) end if end if c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tsaitr = tsaitr + (t1 - t0) ido = 99 c if (msglvl .gt. 1) then call svout (logfil, k+np, h(1,2), ndigit, & '_saitr: main diagonal of matrix H of step K+NP.') if (k+np .gt. 1) then call svout (logfil, k+np-1, h(2,1), ndigit, & '_saitr: sub diagonal of matrix H of step K+NP.') end if end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of ssaitr | c %---------------% c end arpack-ng-3.3.0/SRC/ssapps.f000066400000000000000000000437321260666001200154770ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP shifts implicitly resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix of order KEV+NP. Q is the product of c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi c factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call ssapps c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. dimension of matrix A. c c KEV Integer. (INPUT) c INPUT: KEV+NP is the size of the input matrix H. c OUTPUT: KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Real array of length NP. (INPUT) c The shifts to be applied. c c V Real N by (KEV+NP) array. (INPUT/OUTPUT) c INPUT: V contains the current KEV+NP Arnoldi vectors. c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors c are in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (KEV+NP) by 2 array. (INPUT/OUTPUT) c INPUT: H contains the symmetric tridiagonal matrix of the c Arnoldi factorization with the subdiagonal in the 1st column c starting at H(2,1) and the main diagonal in the 2nd column. c OUTPUT: H contains the updated tridiagonal matrix in the c KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Real array of length (N). (INPUT/OUTPUT) c INPUT: RESID contains the the residual vector r_{k+p}. c OUTPUT: RESID is the updated residual vector rnew_{k}. c c Q Real KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations during the bulge c chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKD Real work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c slartg LAPACK Givens rotation construction routine. c slacpy LAPACK matrix copy routine. c slaset LAPACK matrix initialization routine. c sgemv Level 2 BLAS routine for matrix vector multiplication. c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another. c sscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: sapps.F SID: 2.6 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the subblocks of c the tridiagonal matrix H and not just to the submatrix that it c comes from. This routine assumes that the subdiagonal elements c of H that are stored in h(1:kev+np,1) are nonegative upon input c and enforce this condition upon output. This version incorporates c deflation. See code for documentation. c c\EndLib c c----------------------------------------------------------------------- c subroutine ssapps & ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & h(ldh,2), q(ldq,kev+np), resid(n), shift(np), & v(ldv,kev+np), workd(2*n) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c integer i, iend, istart, itop, j, jj, kplusp, msglvl logical first Real & a1, a2, a3, a4, big, c, epsmch, f, g, r, s save epsmch, first c c c %----------------------% c | External Subroutines | c %----------------------% c external saxpy, scopy, sscal, slacpy, slartg, slaset, svout, & ivout, arscnd, sgemv c c %--------------------% c | External Functions | c %--------------------% c Real & slamch external slamch c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then epsmch = slamch('Epsilon-Machine') first = .false. end if itop = 1 c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msapps c kplusp = kev + np c c %----------------------------------------------% c | Initialize Q to the identity matrix of order | c | kplusp used to accumulate the rotations. | c %----------------------------------------------% c call slaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------------------% c | Apply the np shifts implicitly. Apply each shift to the | c | whole matrix and not just to the submatrix from which it | c | comes. | c %----------------------------------------------------------% c do 90 jj = 1, np c istart = itop c c %----------------------------------------------------------% c | Check for splitting and deflation. Currently we consider | c | an off-diagonal element h(i+1,1) negligible if | c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) | c | for i=1:KEV+NP-1. | c | If above condition tests true then we set h(i+1,1) = 0. | c | Note that h(1:KEV+NP,1) are assumed to be non negative. | c %----------------------------------------------------------% c 20 continue c c %------------------------------------------------% c | The following loop exits early if we encounter | c | a negligible off diagonal element. | c %------------------------------------------------% c do 30 i = istart, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_sapps: occured before shift number.') call svout (logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero iend = i go to 40 end if 30 continue iend = kplusp 40 continue c if (istart .lt. iend) then c c %--------------------------------------------------------% c | Construct the plane rotation G'(istart,istart+1,theta) | c | that attempts to drive h(istart+1,1) to zero. | c %--------------------------------------------------------% c f = h(istart,2) - shift(jj) g = h(istart+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G' * H * G, where G = G(istart,istart+1,theta). | c | This will create a "bulge". | c %-------------------------------------------------------% c a1 = c*h(istart,2) + s*h(istart+1,1) a2 = c*h(istart+1,1) + s*h(istart+1,2) a4 = c*h(istart+1,2) - s*h(istart+1,1) a3 = c*h(istart+1,1) - s*h(istart,2) h(istart,2) = c*a1 + s*a2 h(istart+1,2) = c*a4 - s*a3 h(istart+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 60 j = 1, min(istart+jj,kplusp) a1 = c*q(j,istart) + s*q(j,istart+1) q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1) q(j,istart) = a1 60 continue c c c %----------------------------------------------% c | The following loop chases the bulge created. | c | Note that the previous rotation may also be | c | done within the following loop. But it is | c | kept separate to make the distinction among | c | the bulge chasing sweeps and the first plane | c | rotation designed to drive h(istart+1,1) to | c | zero. | c %----------------------------------------------% c do 70 i = istart+1, iend-1 c c %----------------------------------------------% c | Construct the plane rotation G'(i,i+1,theta) | c | that zeros the i-th bulge that was created | c | by G(i-1,i,theta). g represents the bulge. | c %----------------------------------------------% c f = h(i,1) g = s*h(i+1,1) c c %----------------------------------% c | Final update with G(i-1,i,theta) | c %----------------------------------% c h(i+1,1) = c*h(i+1,1) call slartg (f, g, c, s, r) c c %-------------------------------------------% c | The following ensures that h(1:iend-1,1), | c | the first iend-2 off diagonal of elements | c | H, remain non negative. | c %-------------------------------------------% c if (r .lt. zero) then r = -r c = -c s = -s end if c c %--------------------------------------------% c | Apply rotation to the left and right of H; | c | H <- G * H * G', where G = G(i,i+1,theta) | c %--------------------------------------------% c h(i,1) = r c a1 = c*h(i,2) + s*h(i+1,1) a2 = c*h(i+1,1) + s*h(i+1,2) a3 = c*h(i+1,1) - s*h(i,2) a4 = c*h(i+1,2) - s*h(i+1,1) c h(i,2) = c*a1 + s*a2 h(i+1,2) = c*a4 - s*a3 h(i+1,1) = c*a3 + s*a4 c c %----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G | c %----------------------------------------------------% c do 50 j = 1, min( i+jj, kplusp ) a1 = c*q(j,i) + s*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = a1 50 continue c 70 continue c end if c c %--------------------------% c | Update the block pointer | c %--------------------------% c istart = iend + 1 c c %------------------------------------------% c | Make sure that h(iend,1) is non-negative | c | If not then set h(iend,1) <-- -h(iend,1) | c | and negate the last column of Q. | c | We have effectively carried out a | c | similarity on transformation H | c %------------------------------------------% c if (h(iend,1) .lt. zero) then h(iend,1) = -h(iend,1) call sscal(kplusp, -one, q(1,iend), 1) end if c c %--------------------------------------------------------% c | Apply the same shift to the next block if there is any | c %--------------------------------------------------------% c if (iend .lt. kplusp) go to 20 c c %-----------------------------------------------------% c | Check if we can increase the the start of the block | c %-----------------------------------------------------% c do 80 i = itop, kplusp-1 if (h(i+1,1) .gt. zero) go to 90 itop = itop + 1 80 continue c c %-----------------------------------% c | Finished applying the jj-th shift | c %-----------------------------------% c 90 continue c c %------------------------------------------% c | All shifts have been applied. Check for | c | more possible deflation that might occur | c | after the last shift is applied. | c %------------------------------------------% c do 100 i = itop, kplusp-1 big = abs(h(i,2)) + abs(h(i+1,2)) if (h(i+1,1) .le. epsmch*big) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_sapps: deflation at row/column no.') call svout (logfil, 1, h(i+1,1), ndigit, & '_sapps: the corresponding off diagonal element') end if h(i+1,1) = zero end if 100 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is not necessary if h(kev+1,1) = 0. | c %-------------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call sgemv ('N', n, kplusp, one, v, ldv, & q(1,kev+1), 1, zero, workd(n+1), 1) c c %-------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage that Q is an upper triangular matrix | c | with lower bandwidth np. | c | Place results in v(:,kplusp-kev:kplusp) temporarily. | c %-------------------------------------------------------% c do 130 i = 1, kev call sgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call scopy (n, workd, 1, v(1,kplusp-i+1), 1) 130 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call slacpy ('All', n, kev, v(1,np+1), ldv, v, ldv) c c %--------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the | c | appropriate place if h(kev+1,1) .ne. zero. | c %--------------------------------------------% c if ( h(kev+1,1) .gt. zero ) & call scopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call sscal (n, q(kplusp,kev), resid, 1) if (h(kev+1,1) .gt. zero) & call saxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call svout (logfil, 1, q(kplusp,kev), ndigit, & '_sapps: sigmak of the updated residual vector') call svout (logfil, 1, h(kev+1,1), ndigit, & '_sapps: betak of the updated residual vector') call svout (logfil, kev, h(1,2), ndigit, & '_sapps: updated main diagonal of H for next iteration') if (kev .gt. 1) then call svout (logfil, kev-1, h(2,1), ndigit, & '_sapps: updated sub diagonal of H for next iteration') end if end if c call arscnd (t1) tsapps = tsapps + (t1 - t0) c 9000 continue return c c %---------------% c | End of ssapps | c %---------------% c end arpack-ng-3.3.0/SRC/ssaup2.f000066400000000000000000000767071260666001200154130ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssaup2 c c\Description: c Intermediate level interface called by ssaupd. c c\Usage: c call ssaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, c IPNTR, WORKD, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in ssaupd. c MODE, ISHIFT, MXITER: see the definition of IPARAM in ssaupd. c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi/Lanczos iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Tridiagonal matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Real N by (NEV+NP) array. (INPUT/OUTPUT) c The Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Real (NEV+NP) by 2 array. (OUTPUT) c H is used to store the generated symmetric tridiagonal matrix c The subdiagonal is stored in the first column of H starting c at H(2,1). The main diagonal is stored in the second column c of H starting at H(1,2). If ssaup2 converges store the c B-norm of the final residual vector in H(1,1). c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Real array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Real array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ. c c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Real array of length at least 3*(NEV+NP). (INPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in the computation of the c tridiagonal eigenvalue problem, the calculation and c application of the shifts and convergence checking. c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations c of WORKL are used in reverse communication to hold the user c supplied shifts. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in one of c the spectral transformation modes. X is the current c operand. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Lanczos iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in ssaupd. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: All possible eigenvalues of OP has been found. c NP returns the size of the invariant subspace c spanning the operator OP. c = 2: No shifts could be applied. c = -8: Error return from trid. eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Lanczos factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Routines called: c sgetv0 ARPACK initial vector generation routine. c ssaitr ARPACK Lanczos factorization routine. c ssapps ARPACK application of implicit shifts routine. c ssconv ARPACK convergence of Ritz values routine. c sseigt ARPACK compute Ritz values and error bounds routine. c ssgets ARPACK reorder Ritz values and error bounds routine. c ssortr ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c scopy Level 1 BLAS that copies one vector to another. c sdot Level 1 BLAS that computes the scalar product of two vectors. c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.4' c xx/xx/95: Version ' 2.4'. (R.B. Lehoucq) c c\SCCS Information: @(#) c FILE: saup2.F SID: 2.7 DATE OF SID: 5/19/98 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine ssaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter, & n, mode, nev, np Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Real & bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n), & ritz(nev+np), v(ldv,nev+np), workd(3*n), & workl(3*(nev+np)) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c character wprime*2 logical cnorm, getv0, initv, update, ushift integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0, & np0, nptemp, nevd2, nevm2, kp(3) Real & rnorm, temp, eps23 save cnorm, getv0, initv, update, ushift, & iter, kplusp, msglvl, nconv, nev0, np0, & rnorm, eps23 c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, sgetv0, ssaitr, sscal, ssconv, sseigt, ssgets, & ssapps, ssortr, svout, ivout, arscnd, sswap c c %--------------------% c | External Functions | c %--------------------% c Real & sdot, snrm2, slamch external sdot, snrm2, slamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msaup2 c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0/3.0E+0) c c %-------------------------------------% c | nev0 and np0 are integer variables | c | hold the initial values of NEV & NP | c %-------------------------------------% c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvlues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev0 + np0 nconv = 0 iter = 0 c c %--------------------------------------------% c | Set flags for computing the first NEV steps | c | of the Lanczos factorization. | c %--------------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call sgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. zero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1200 end if getv0 = .false. ido = 0 end if c c %------------------------------------------------------------% c | Back from reverse communication: continue with update step | c %------------------------------------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Lanczos factorization | c %----------------------------------------------------------% c call ssaitr (ido, bmat, n, 0, nev0, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | ssaitr was unable to build an Lanczos factorization | c | of length NEV0. INFO is returned with the size of | c | the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N LANCZOS I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Lanczos | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_saup2: **** Start of major iteration number ****') end if if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_saup2: The length of the current Lanczos factorization') call ivout (logfil, 1, np, ndigit, & '_saup2: Extend the Lanczos factorization by') end if c c %------------------------------------------------------------% c | Compute NP additional steps of the Lanczos factorization. | c %------------------------------------------------------------% c ido = 0 20 continue update = .true. c call ssaitr (ido, bmat, n, nev, np, mode, resid, rnorm, v, & ldv, h, ldh, ipntr, workd, info) c c %---------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP and possibly B | c %---------------------------------------------------% c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then c c %-----------------------------------------------------% c | ssaitr was unable to build an Lanczos factorization | c | of length NEV0+NP0. INFO is returned with the size | c | of the factorization built. Exit main loop. | c %-----------------------------------------------------% c np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call svout (logfil, 1, rnorm, ndigit, & '_saup2: Current B-norm of residual for factorization') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current symmetric tridiagonal matrix. | c %--------------------------------------------------------% c call sseigt (rnorm, kplusp, h, ldh, ritz, bounds, workl, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %----------------------------------------------------% c | Make a copy of eigenvalues and corresponding error | c | bounds obtained from _seigt. | c %----------------------------------------------------% c call scopy(kplusp, ritz, 1, workl(kplusp+1), 1) call scopy(kplusp, bounds, 1, workl(2*kplusp+1), 1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The selection is based on the requested number of | c | eigenvalues instead of the current NEV and NP to | c | prevent possible misconvergence. | c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) | c | * Shifts := RITZ(1:NP) := WORKL(1:NP) | c %---------------------------------------------------% c nev = nev0 np = np0 call ssgets (ishift, which, nev, np, ritz, bounds, workl) c c %-------------------% c | Convergence test. | c %-------------------% c call scopy (nev, bounds(np+1), 1, workl(np+1), 1) call ssconv (nev, ritz(np+1), workl(np+1), tol, nconv) c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call ivout (logfil, 3, kp, ndigit, & '_saup2: NEV, NP, NCONV are') call svout (logfil, kplusp, ritz, ndigit, & '_saup2: The eigenvalues of H') call svout (logfil, kplusp, bounds, ndigit, & '_saup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP since we don't want to | c | swap overlapping locations. | c %------------------------------------------------% c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically decreasing | c | order first then swap low end of the spectrum next | c | to high end in appropriate locations. | c | NOTE: when np < floor(nev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c wprime = 'SA' call ssortr (wprime, .true., kplusp, ritz, bounds) nevd2 = nev0 / 2 nevm2 = nev0 - nevd2 if ( nev .gt. 1 ) then call sswap ( min(nevd2,np), ritz(nevm2+1), 1, & ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1) call sswap ( min(nevd2,np), bounds(nevm2+1), 1, & bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1) end if c else c c %--------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the an order that | c | is opposite to WHICH, and apply the resulting | c | order to BOUNDS. The eigenvalues are sorted so | c | that the wanted part are always within the first | c | NEV locations. | c %--------------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LA') wprime = 'SA' if (which .eq. 'SA') wprime = 'LA' c call ssortr (wprime, .true., kplusp, ritz, bounds) c end if c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23,magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)/temp 35 continue c c %----------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | esitmates. This will push all the converged ones | c | towards the front of ritzr, ritzi, bounds | c | (in the case when NCONV < NEV.) | c %----------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 temp = max( eps23, abs(ritz(j)) ) bounds(j) = bounds(j)*temp 40 continue c c %--------------------------------------------------% c | Sort the "converged" Ritz values again so that | c | the "threshold" values and their associated Ritz | c | estimates appear at the appropriate position in | c | ritz and bound. | c %--------------------------------------------------% c if (which .eq. 'BE') then c c %------------------------------------------------% c | Sort the "converged" Ritz values in increasing | c | order. The "threshold" values are in the | c | middle. | c %------------------------------------------------% c wprime = 'LA' call ssortr(wprime, .true., nconv, ritz, bounds) c else c c %----------------------------------------------% c | In LM, SM, LA, SA case, sort the "converged" | c | Ritz values according to WHICH so that the | c | "threshold" value appears at the front of | c | ritz. | c %----------------------------------------------% call ssortr(which, .true., nconv, ritz, bounds) c end if c c %------------------------------------------% c | Use h( 1,1 ) as storage to communicate | c | rnorm to _seupd if needed | c %------------------------------------------% c h(1,1) = rnorm c if (msglvl .gt. 1) then call svout (logfil, kplusp, ritz, ndigit, & '_saup2: Sorted Ritz values.') call svout (logfil, kplusp, bounds, ndigit, & '_saup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if (nconv .lt. nev .and. ishift .eq. 1) then c c %---------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the number | c | of Ritz values and the shifts. | c %---------------------------------------------------% c nevbef = nev nev = nev + min (nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 2) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call ssgets (ishift, which, nev, np, ritz, bounds, & workl) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_saup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_saup2: NEV and NP are') call svout (logfil, nev, ritz(np+1), ndigit, & '_saup2: "wanted" Ritz values.') call svout (logfil, nev, bounds(np+1), ndigit, & '_saup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-----------------------------------------------------% c | User specified shifts: reverse communication to | c | compute the shifts. They are returned in the first | c | NP locations of WORKL. | c %-----------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if c 50 continue c c %------------------------------------% c | Back from reverse communication; | c | User specified shifts are returned | c | in WORKL(1:*NP) | c %------------------------------------% c ushift = .false. c c c %---------------------------------------------------------% c | Move the NP shifts to the first NP locations of RITZ to | c | free up WORKL. This is for the non-exact shift case; | c | in the exact shift case, ssgets already handles this. | c %---------------------------------------------------------% c if (ishift .eq. 0) call scopy (np, workl, 1, ritz, 1) c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_saup2: The number of shifts to apply ') call svout (logfil, np, workl, ndigit, & '_saup2: shifts selected') if (ishift .eq. 1) then call svout (logfil, np, bounds, ndigit, & '_saup2: corresponding Ritz estimates') end if end if c c %---------------------------------------------------------% c | Apply the NP0 implicit shifts by QR bulge chasing. | c | Each shift is applied to the entire tridiagonal matrix. | c | The first 2*N locations of WORKD are used as workspace. | c | After ssapps is done, we have a Lanczos | c | factorization of length NEV. | c %---------------------------------------------------------% c call ssapps (n, nev, np, ritz, v, ldv, h, ldh, resid, q, ldq, & workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to ssaitr. | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call scopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call scopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then rnorm = sdot (n, resid, 1, workd, 1) rnorm = sqrt(abs(rnorm)) else if (bmat .eq. 'I') then rnorm = snrm2(n, resid, 1) end if cnorm = .false. 130 continue c if (msglvl .gt. 2) then call svout (logfil, 1, rnorm, ndigit, & '_saup2: B-norm of residual for NEV factorization') call svout (logfil, nev, h(1,2), ndigit, & '_saup2: main diagonal of compressed H matrix') call svout (logfil, nev-1, h(2,1), ndigit, & '_saup2: subdiagonal of compressed H matrix') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error exit | c %------------% c call arscnd (t1) tsaup2 = t1 - t0 c 9000 continue return c c %---------------% c | End of ssaup2 | c %---------------% c end arpack-ng-3.3.0/SRC/ssaupd.f000066400000000000000000000703721260666001200154650ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssaupd c c\Description: c c Reverse communication interface for the Implicitly Restarted Arnoldi c Iteration. For symmetric problems this reduces to a variant of the Lanczos c method. This method has been designed to compute approximations to a c few eigenpairs of a linear operator OP that is real and symmetric c with respect to a real positive semi-definite symmetric matrix B, c i.e. c c B*OP = (OP`)*B. c c Another way to express this condition is c c < x,OPy > = < OPx,y > where < z,w > = z`Bw . c c In the standard eigenproblem B is the identity matrix. c ( A` denotes transpose of A) c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c ssaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x, A symmetric c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite c ===> OP = (inv[K - sigma*M])*M and B = M. c ===> Shift-and-Invert mode c c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite, c KG symmetric indefinite c ===> OP = (inv[K - sigma*KG])*K and B = K. c ===> Buckling mode c c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M. c ===> Cayley transformed mode c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call ssaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to ssaupd. IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c ssaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c (If Mode = 2 see remark 5 below) c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3,4 and 5, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute the IPARAM(8) shifts where c IPNTR(11) is the pointer into WORKL for c placing the shifts. See remark 6 below. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c Specify which of the Ritz values of OP to compute. c c 'LA' - compute the NEV largest (algebraic) eigenvalues. c 'SA' - compute the NEV smallest (algebraic) eigenvalues. c 'LM' - compute the NEV largest (in magnitude) eigenvalues. c 'SM' - compute the NEV smallest (in magnitude) eigenvalues. c 'BE' - compute NEV eigenvalues, half from each end of the c spectrum. When NEV is odd, compute one more from the c high end than from the low end. c (see remark 1 below) c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N. c c TOL Real scalar. (INPUT) c Stopping criterion: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)). c If TOL .LE. 0. is passed a default is set: c DEFAULT = SLAMCH('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine SLAMCH). c c RESID Real array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V (less than or equal to N). c This will indicate how many Lanczos vectors are generated c at each iteration. After the startup phase in which NEV c Lanczos vectors are generated, the algorithm generates c NCV-NEV Lanczos vectors at each subsequent update iteration. c Most of the cost in generating each Lanczos vector is in the c matrix-vector product OP*x. (See remark 4 below). c c V Real N by NCV array. (OUTPUT) c The NCV columns of V contain the Lanczos basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to restart c the Arnoldi iteration in an implicit fashion. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are provided by the user via c reverse communication. The NCV eigenvalues of c the current tridiagonal matrix T are returned in c the part of WORKL array corresponding to RITZ. c See remark 6 below. c ISHIFT = 1: exact shifts with respect to the reduced c tridiagonal matrix T. This is equivalent to c restarting the iteration with a starting vector c that is a linear combination of Ritz vectors c associated with the "wanted" Ritz values. c ------------------------------------------------------------- c c IPARAM(2) = LEVEC c No longer referenced. See remark 2 below. c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3,4,5; See under \Description of ssaupd for the c five modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), ssaupd returns NP, the number c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark c 6 below. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 11. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Lanczos iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL. c IPNTR(6): pointer to the NCV RITZ values array in WORKL. c IPNTR(7): pointer to the Ritz estimates in array WORKL associated c with the Ritz values located in RITZ in WORKL. c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below. c c Note: IPNTR(8:10) is only referenced by sseupd. See Remark 2. c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c sseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration. Upon termination c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired c subroutine sseupd uses this output. c See Data Distribution Note below. c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least NCV**2 + 8*NCV . c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -4: The maximum number of Arnoldi update iterations allowed c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array WORKL is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Informatinal error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable. c = -12: IPARAM(1) must be equal to 0 or 1. c = -13: NEV and WHICH = 'BE' are incompatable. c = -9999: Could not build an Arnoldi factorization. c IPARAM(5) returns the size of the current Arnoldi c factorization. The user is advised to check that c enough workspace and array storage has been allocated. c c c\Remarks c 1. The converged Ritz values are always returned in ascending c algebraic order. The computed Ritz values are approximate c eigenvalues of OP. The selection of WHICH should be made c with this in mind when Mode = 3,4,5. After convergence, c approximate eigenvalues of the original problem may be obtained c with the ARPACK subroutine sseupd. c c 2. If the Ritz vectors corresponding to the converged Ritz values c are needed, the user must call sseupd immediately following completion c of ssaupd. This is new starting with version 2.1 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requrement is that NCV > NEV. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user c must do the following. When IDO = 1, Y = OP * X is to be computed. c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user c must overwrite X with A*X. Y is then the solution to the linear set c of equations B*Y = A*X. c c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) shifts in locations: c 1 WORKL(IPNTR(11)) c 2 WORKL(IPNTR(11)+1) c . c . c . c NP WORKL(IPNTR(11)+NP-1). c c The eigenvalues of the current tridiagonal matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the c order defined by WHICH. The associated Ritz estimates are located in c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL) c DECOMPOSE D1(N), D2(N,NCV) c ALIGN RESID(I) with D1(I) c ALIGN V(I,J) with D2(I,J) c ALIGN WORKD(I) with D1(I) range (1:N) c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N) c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N) c DISTRIBUTE D1(BLOCK), D2(BLOCK,:) c REPLICATED WORKL(LWORKL) c c Cray MPP syntax: c =============== c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL) c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:) c REPLICATED WORKL(LWORKL) c c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral c Transformations in a k-Step Arnoldi Method". In Preparation. c c\Routines called: c ssaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c sstats ARPACK routine that initialize timing and other statistics c variables. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c slamch LAPACK routine that determines machine constants. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.4' c c\SCCS Information: @(#) c FILE: saupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine ssaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(11) Real & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0 , zero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz, j save bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, msglvl, mxiter, mode, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external ssaup2, svout, ivout, arscnd, sstats c c %--------------------% c | External Functions | c %--------------------% c Real & slamch external slamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call sstats call arscnd (t0) msglvl = msaupd c ierr = 0 ishift = iparam(1) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c c %----------------% c | Error checking | c %----------------% c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev .or. ncv .gt. n) then ierr = -3 end if c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c %----------------------------------------------% c np = ncv - nev c if (mxiter .le. 0) ierr = -4 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 c if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7 if (mode .lt. 1 .or. mode .gt. 5) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 else if (ishift .lt. 0 .or. ishift .gt. 1) then ierr = -12 else if (nev .eq. 1 .and. which .eq. 'BE') then ierr = -13 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. zero) tol = slamch('EpsMach') c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, ncv**2 + 8*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds | c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q | c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace | c %-------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + 2*ldh bounds = ritz + ncv iq = bounds + ncv iw = iq + ncv**2 next = iw + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = bounds ipntr(11) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Lanczos Iteration. | c %-------------------------------------------------------% c call ssaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd, & info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP or shifts. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within ssaup2. | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_saupd: number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_saupd: number of "converged" Ritz values') call svout (logfil, np, workl(Ritz), ndigit, & '_saupd: final Ritz values') call svout (logfil, np, workl(Bounds), ndigit, & '_saupd: corresponding error bounds') end if c call arscnd (t1) tsaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref, & tgetv0, tseigt, tsgets, tsapps, tsconv 1000 format (//, & 5x, '==========================================',/ & 5x, '= Symmetric implicit Arnoldi update code =',/ & 5x, '= Version Number:', ' 2.4' , 19x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 14x, ' =',/ & 5x, '==========================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '==========================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in saup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6) end if c 9000 continue c return c c %---------------% c | End of ssaupd | c %---------------% c end arpack-ng-3.3.0/SRC/ssconv.f000066400000000000000000000064561260666001200155030ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssconv c c\Description: c Convergence testing for the symmetric Arnoldi eigenvalue routine. c c\Usage: c call ssconv c ( N, RITZ, BOUNDS, TOL, NCONV ) c c\Arguments c N Integer. (INPUT) c Number of Ritz values to check for convergence. c c RITZ Real array of length N. (INPUT) c The Ritz values to be checked for convergence. c c BOUNDS Real array of length N. (INPUT) c Ritz estimates associated with the Ritz values in RITZ. c c TOL Real scalar. (INPUT) c Desired relative accuracy for a Ritz value to be considered c "converged". c c NCONV Integer scalar. (OUTPUT) c Number of "converged" Ritz values. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines called: c arscnd ARPACK utility routine for timing. c slamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sconv.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2 c c\Remarks c 1. Starting with version 2.4, this routine no longer uses the c Parlett strategy using the gap conditions. c c\EndLib c c----------------------------------------------------------------------- c subroutine ssconv (n, ritz, bounds, tol, nconv) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer n, nconv Real & tol c c %-----------------% c | Array Arguments | c %-----------------% c Real & ritz(n), bounds(n) c c %---------------% c | Local Scalars | c %---------------% c integer i Real & temp, eps23 c c %-------------------% c | External routines | c %-------------------% c Real & slamch external slamch c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c call arscnd (t0) c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0) c nconv = 0 do 10 i = 1, n c c %-----------------------------------------------------% c | The i-th Ritz value is considered "converged" | c | when: bounds(i) .le. TOL*max(eps23, abs(ritz(i))) | c %-----------------------------------------------------% c temp = max( eps23, abs(ritz(i)) ) if ( bounds(i) .le. tol*temp ) then nconv = nconv + 1 end if c 10 continue c call arscnd (t1) tsconv = tsconv + (t1 - t0) c return c c %---------------% c | End of ssconv | c %---------------% c end arpack-ng-3.3.0/SRC/sseigt.f000066400000000000000000000117551260666001200154640ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: sseigt c c\Description: c Compute the eigenvalues of the current symmetric tridiagonal matrix c and the corresponding error bounds given the current residual norm. c c\Usage: c call sseigt c ( RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR ) c c\Arguments c RNORM Real scalar. (INPUT) c RNORM contains the residual norm corresponding to the current c symmetric tridiagonal matrix H. c c N Integer. (INPUT) c Size of the symmetric tridiagonal matrix H. c c H Real N by 2 array. (INPUT) c H contains the symmetric tridiagonal matrix with the c subdiagonal in the first column starting at H(2,1) and the c main diagonal in second column. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c EIG Real array of length N. (OUTPUT) c On output, EIG contains the N eigenvalues of H possibly c unsorted. The BOUNDS arrays are returned in the c same sorted order as EIG. c c BOUNDS Real array of length N. (OUTPUT) c On output, BOUNDS contains the error estimates corresponding c to the eigenvalues EIG. This is equal to RNORM times the c last components of the eigenvectors corresponding to the c eigenvalues in EIG. c c WORKL Real work array of length 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from sstqrb. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c sstqrb ARPACK routine that computes the eigenvalues and the c last components of the eigenvectors of a symmetric c and tridiagonal matrix. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.4' c c\SCCS Information: @(#) c FILE: seigt.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine sseigt & ( rnorm, n, h, ldh, eig, bounds, workl, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, ldh, n Real & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Real & eig(n), bounds(n), h(ldh,2), workl(3*n) c c %------------% c | Parameters | c %------------% c Real & zero parameter (zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c integer i, k, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external scopy, sstqrb, svout, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mseigt c if (msglvl .gt. 0) then call svout (logfil, n, h(1,2), ndigit, & '_seigt: main diagonal of matrix H') if (n .gt. 1) then call svout (logfil, n-1, h(2,1), ndigit, & '_seigt: sub diagonal of matrix H') end if end if c call scopy (n, h(1,2), 1, eig, 1) call scopy (n-1, h(2,1), 1, workl, 1) call sstqrb (n, eig, workl, bounds, workl(n+1), ierr) if (ierr .ne. 0) go to 9000 if (msglvl .gt. 1) then call svout (logfil, n, bounds, ndigit, & '_seigt: last row of the eigenvector matrix for H') end if c c %-----------------------------------------------% c | Finally determine the error bounds associated | c | with the n Ritz values of H. | c %-----------------------------------------------% c do 30 k = 1, n bounds(k) = rnorm*abs(bounds(k)) 30 continue c call arscnd (t1) tseigt = tseigt + (t1 - t0) c 9000 continue return c c %---------------% c | End of sseigt | c %---------------% c end arpack-ng-3.3.0/SRC/ssesrt.f000066400000000000000000000123101260666001200154750ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssesrt c c\Description: c Sort the array X in the order specified by WHICH and optionally c apply the permutation to the columns of the matrix A. c c\Usage: c call ssesrt c ( WHICH, APPLY, N, X, NA, A, LDA) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> X is sorted into increasing order of magnitude. c 'SM' -> X is sorted into decreasing order of magnitude. c 'LA' -> X is sorted into increasing order of algebraic. c 'SA' -> X is sorted into decreasing order of algebraic. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to A. c APPLY = .FALSE. -> do not apply the sorted order to A. c c N Integer. (INPUT) c Dimension of the array X. c c X Real array of length N. (INPUT/OUTPUT) c The array to be sorted. c c NA Integer. (INPUT) c Number of rows of the matrix A. c c A Real array of length NA by N. (INPUT/OUTPUT) c c LDA Integer. (INPUT) c Leading dimension of A. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines c sswap Level 1 BLAS that swaps the contents of two vectors. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.1'. c Adapted from the sort routine in LANSO and c the ARPACK code ssortr c c\SCCS Information: @(#) c FILE: sesrt.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine ssesrt (which, apply, n, x, na, a, lda) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer lda, n, na c c %-----------------% c | Array Arguments | c %-----------------% c Real & x(0:n-1), a(lda, 0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Real & temp c c %----------------------% c | External Subroutines | c %----------------------% c external sswap c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'SA') then c c X is sorted into decreasing order of algebraic. c 10 continue if (igap .eq. 0) go to 9000 do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c if (x(j).lt.x(j+igap)) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 30 endif j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c X is sorted into decreasing order of magnitude. c 40 continue if (igap .eq. 0) go to 9000 do 60 i = igap, n-1 j = i-igap 50 continue c if (j.lt.0) go to 60 c if (abs(x(j)).lt.abs(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LA') then c c X is sorted into increasing order of algebraic. c 70 continue if (igap .eq. 0) go to 9000 do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (x(j).gt.x(j+igap)) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'LM') then c c X is sorted into increasing order of magnitude. c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (abs(x(j)).gt.abs(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1) else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 end if c 9000 continue return c c %---------------% c | End of ssesrt | c %---------------% c end arpack-ng-3.3.0/SRC/sseupd.f000066400000000000000000001035071260666001200154660ustar00rootroot00000000000000c\BeginDoc c c\Name: sseupd c c\Description: c c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) the corresponding approximate eigenvectors, c c (2) an orthonormal (Lanczos) basis for the associated approximate c invariant subspace, c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c (Lanczos) basis is always computed. There is an additional storage cost c of n*nev if both are requested (in this case a separate array Z must be c supplied). c c These quantities are obtained from the Lanczos factorization computed c by SSAUPD for the linear operator OP prescribed by the MODE selection c (see IPARAM(7) in SSAUPD documentation.) SSAUPD must be called before c this routine is called. These approximate eigenvalues and vectors are c commonly called Ritz values and Ritz vectors respectively. They are c referred to as such in the comments that follow. The computed orthonormal c basis for the invariant subspace corresponding to these Ritz values is c referred to as a Lanczos basis. c c See documentation in the header of the subroutine SSAUPD for a definition c of OP as well as other terms and the relation of computed Ritz values c and vectors of OP with respect to the given problem A*z = lambda*B*z. c c The approximate eigenvalues of the original problem are returned in c ascending algebraic order. The user may elect to call this routine c once for each desired Ritz vector and store it peripherally if desired. c There is also the option of computing a selected set of these vectors c with a single call. c c\Usage: c call sseupd c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL, c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO ) c c RVEC LOGICAL (INPUT) c Specifies whether Ritz vectors corresponding to the Ritz value c approximations to the eigenproblem A*z = lambda*B*z are computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors. c c HOWMNY Character*1 (INPUT) c Specifies how many Ritz vectors are wanted and the form of Z c the matrix of Ritz vectors. See remark 1 below. c = 'A': compute NEV Ritz vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' , SELECT is used as a workspace for c reordering the Ritz values. c c D Real array of dimension NEV. (OUTPUT) c On exit, D contains the Ritz value approximations to the c eigenvalues of A*z = lambda*B*z. The values are returned c in ascending order. If IPARAM(7) = 3,4,5 then D represents c the Ritz values of OP computed by ssaupd transformed to c those of the original eigensystem A*z = lambda*B*z. If c IPARAM(7) = 1,2 then the Ritz values of OP are the same c as the those of A*z = lambda*B*z. c c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT) c On exit, Z contains the B-orthonormal Ritz vectors of the c eigensystem A*z = lambda*B*z corresponding to the Ritz c value approximations. c If RVEC = .FALSE. then Z is not referenced. c NOTE: The array Z may be set equal to first NEV columns of the c Arnoldi/Lanczos basis array V computed by SSAUPD. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1. c c SIGMA Real (INPUT) c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if c IPARAM(7) = 1 or 2. c c c **** The remaining arguments MUST be the same as for the **** c **** call to SSAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, INFO c c must be passed directly to SSEUPD following the last call c to SSAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to SSAUPD and the call to SSEUPD. c c Two of these parameters (WORKL, INFO) are also output parameters: c c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:4*ncv) contains information obtained in c ssaupd. They are not changed by sseupd. c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the c untransformed Ritz values, the computed error estimates, c and the associated eigenvector matrix of H. c c Note: IPNTR(8:10) contains the pointer into WORKL for addresses c of the above information computed by sseupd. c ------------------------------------------------------------- c IPNTR(8): pointer to the NCV RITZ values of the original system. c IPNTR(9): pointer to the NCV corresponding error bounds. c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors c of the tridiagonal matrix T. Only referenced by c sseupd if RVEC = .TRUE. See Remarks. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV must be greater than NEV and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'. c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from trid. eigenvalue calculation; c Information error from LAPACK routine ssteqr. c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3,4,5. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: NEV and WHICH = 'BE' are incompatible. c = -14: SSAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true. c = -16: HOWMNY = 'S' not yet implemented c = -17: SSEUPD got a different count of the number of converged c Ritz values than SSAUPD got. This indicates the user c probably made an error in passing data from SSAUPD to c SSEUPD or that the data was modified before entering c SSEUPD. c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall, c 1980. c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program", c Computer Physics Communications, 53 (1989), pp 169-179. c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to c Implement the Spectral Transformation", Math. Comp., 48 (1987), c pp 663-673. c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems", c SIAM J. Matr. Anal. Apps., January (1993). c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines c for Updating the QR decomposition", ACM TOMS, December 1990, c Volume 16 Number 4, pp 369-377. c c\Remarks c 1. The converged Ritz values are always returned in increasing c (algebraic) order. c c 2. Currently only HOWMNY = 'A' is implemented. It is included at this c stage for the user who wants to incorporate it. c c\Routines called: c ssesrt ARPACK routine that sorts an array X, and applies the c corresponding permutation to a matrix A. c ssortr ssortr ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c svout ARPACK utility routine that prints vectors. c sgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c slacpy LAPACK matrix copy routine. c slamch LAPACK routine that determines machine constants. c sorm2r LAPACK routine that applies an orthogonal matrix in c factored form. c ssteqr LAPACK routine that computes eigenvalues and eigenvectors c of a tridiagonal matrix. c sger Level 2 BLAS rank one update to a matrix. c scopy Level 1 BLAS that copies one vector to another . c snrm2 Level 1 BLAS that computes the norm of a vector. c sscal Level 1 BLAS that scales a vector. c sswap Level 1 BLAS that swaps the contents of two vectors. c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/15/93: Version ' 2.1' c c\SCCS Information: @(#) c FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine sseupd(rvec , howmny, select, d , & z , ldz , sigma , bmat , & n , which , nev , tol , & resid , ncv , v , ldv , & iparam, ipntr , workd , workl, & lworkl, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Real & sigma, tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(7), ipntr(11) logical select(ncv) Real & d(nev) , resid(n) , v(ldv,ncv), & z(ldz, nev), workd(2*n), workl(lworkl) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0 , zero = 0.0E+0 ) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds , ierr , ih , ihb , ihd , & iq , iw , j , k , ldh , & ldq , mode , msglvl, nconv , next , & ritz , irz , ibd , np , ishift, & leftptr, rghtptr, numcnv, jj Real & bnorm2 , rnorm, temp, temp1, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external scopy , sger , sgeqr2, slacpy, sorm2r, sscal, & ssesrt, ssteqr, sswap , svout , ivout , ssortr c c %--------------------% c | External Functions | c %--------------------% c Real & snrm2, slamch external snrm2, slamch c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mseupd mode = iparam(7) nconv = iparam(5) info = 0 c c %--------------% c | Quick return | c %--------------% c if (nconv .eq. 0) go to 9000 ierr = 0 c if (nconv .le. 0) ierr = -14 if (n .le. 0) ierr = -1 if (nev .le. 0) ierr = -2 if (ncv .le. nev .or. ncv .gt. n) ierr = -3 if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LA' .and. & which .ne. 'SA' .and. & which .ne. 'BE') ierr = -5 if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6 if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) & ierr = -15 if (rvec .and. howmny .eq. 'S') ierr = -16 c if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7 c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else if (mode .eq. 4 ) then type = 'BUCKLE' else if (mode .eq. 5 ) then type = 'CAYLEY' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %-------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:2*ncv) := generated tridiagonal matrix H | c | The subdiagonal is stored in workl(2:ncv). | c | The dead spot is workl(1) but upon exiting | c | ssaupd stores the B-norm of the last residual | c | vector in workl(1). We use this !!! | c | workl(2*ncv+1:2*ncv+ncv) := ritz values | c | The wanted values are in the first NCONV spots. | c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates | c | The wanted values are in the first NCONV spots. | c | NOTE: workl(1:4*ncv) is set by ssaupd and is not | c | modified by sseupd. | c %-------------------------------------------------------% c c %-------------------------------------------------------% c | The following is used and set by sseupd. | c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the diagonal of H. Upon EXIT contains the NCV | c | Ritz values of the original system. The first | c | NCONV spots have the wanted values. If MODE = | c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). | c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during | c | computation of the eigenvectors of H. Stores | c | the subdiagonal of H. Upon EXIT contains the | c | NCV corresponding Ritz estimates of the | c | original system. The first NCONV spots have the | c | wanted values. If MODE = 1,2 then will equal | c | workl(3*ncv+1:4*ncv). | c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is | c | the eigenvector matrix for H as returned by | c | ssteqr. Not referenced if RVEC = .False. | c | Ordering follows that of workl(4*ncv+1:5*ncv) | c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := | c | Workspace. Needed by ssteqr and by sseupd. | c | GRAND total of NCV*(NCV+8) locations. | c %-------------------------------------------------------% c c ih = ipntr(5) ritz = ipntr(6) bounds = ipntr(7) ldh = ncv ldq = ncv ihd = bounds + ldh ihb = ihd + ldh iq = ihb + ldh iw = iq + ldh*ncv next = iw + 2*ncv ipntr(4) = next ipntr(8) = ihd ipntr(9) = ihb ipntr(10) = iq c c %----------------------------------------% c | irz points to the Ritz values computed | c | by _seigt before exiting _saup2. | c | ibd points to the Ritz estimates | c | computed by _seigt before exiting | c | _saup2. | c %----------------------------------------% c irz = ipntr(11)+ncv ibd = irz+ncv c c c %---------------------------------% c | Set machine dependent constant. | c %---------------------------------% c eps23 = slamch('Epsilon-Machine') eps23 = eps23**(2.0E+0 / 3.0E+0 ) c c %---------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c | BNORM2 is the 2 norm of B*RESID(1:N). | c | Upon exit of ssaupd WORKD(1:N) has | c | B*RESID(1:N). | c %---------------------------------------% c rnorm = workl(ih) if (bmat .eq. 'I') then bnorm2 = rnorm else if (bmat .eq. 'G') then bnorm2 = snrm2(n, workd, 1) end if c if (msglvl .gt. 2) then call svout(logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values passed in from _SAUPD.') call svout(logfil, ncv, workl(ibd), ndigit, & '_seupd: Ritz estimates passed in from _SAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(bound) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call ssgets(ishift, which , nev , & np , workl(irz) , workl(bounds), & workl) c if (msglvl .gt. 2) then call svout(logfil, ncv, workl(irz), ndigit, & '_seupd: Ritz values after calling _SGETS.') call svout(logfil, ncv, workl(bounds), ndigit, & '_seupd: Ritz value indices after calling _SGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv temp1 = max(eps23, abs(workl(irz+ncv-j)) ) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & workl(ibd+jj-1) .le. tol*temp1) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by _saupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the _saupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_seupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_seupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -17 go to 9000 end if c c %-----------------------------------------------------------% c | Call LAPACK routine _steqr to compute the eigenvalues and | c | eigenvectors of the final symmetric tridiagonal matrix H. | c | Initialize the eigenvector matrix Q to the identity. | c %-----------------------------------------------------------% c call scopy(ncv-1, workl(ih+1), 1, workl(ihb), 1) call scopy(ncv, workl(ih+ldh), 1, workl(ihd), 1) c call ssteqr('Identity', ncv, workl(ihd), workl(ihb), & workl(iq) , ldq, workl(iw), ierr) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call scopy(ncv, workl(iq+ncv-1), ldq, workl(iw), 1) call svout(logfil, ncv, workl(ihd), ndigit, & '_seupd: NCV Ritz values of the final H matrix') call svout(logfil, ncv, workl(iw), ndigit, & '_seupd: last row of the eigenvector matrix for H') end if c if (reord) then c c %---------------------------------------------% c | Reordered the eigenvalues and eigenvectors | c | computed by _steqr so that the "converged" | c | eigenvalues appear in the first NCONV | c | positions of workl(ihd), and the associated | c | eigenvectors appear in the first NCONV | c | columns. | c %---------------------------------------------% c leftptr = 1 rghtptr = ncv c if (ncv .eq. 1) go to 30 c 20 if (select(leftptr)) then c c %-------------------------------------------% c | Search, from the left, for the first Ritz | c | value that has not converged. | c %-------------------------------------------% c leftptr = leftptr + 1 c else if ( .not. select(rghtptr)) then c c %----------------------------------------------% c | Search, from the right, the first Ritz value | c | that has converged. | c %----------------------------------------------% c rghtptr = rghtptr - 1 c else c c %----------------------------------------------% c | Swap the Ritz value on the left that has not | c | converged with the Ritz value on the right | c | that has converged. Swap the associated | c | eigenvector of the tridiagonal matrix H as | c | well. | c %----------------------------------------------% c temp = workl(ihd+leftptr-1) workl(ihd+leftptr-1) = workl(ihd+rghtptr-1) workl(ihd+rghtptr-1) = temp call scopy(ncv, workl(iq+ncv*(leftptr-1)), 1, & workl(iw), 1) call scopy(ncv, workl(iq+ncv*(rghtptr-1)), 1, & workl(iq+ncv*(leftptr-1)), 1) call scopy(ncv, workl(iw), 1, & workl(iq+ncv*(rghtptr-1)), 1) leftptr = leftptr + 1 rghtptr = rghtptr - 1 c end if c if (leftptr .lt. rghtptr) go to 20 c end if c 30 if (msglvl .gt. 2) then call svout (logfil, ncv, workl(ihd), ndigit, & '_seupd: The eigenvalues of H--reordered') end if c c %----------------------------------------% c | Load the converged Ritz values into D. | c %----------------------------------------% c call scopy(nconv, workl(ihd), 1, d, 1) c else c c %-----------------------------------------------------% c | Ritz vectors not required. Load Ritz values into D. | c %-----------------------------------------------------% c call scopy(nconv, workl(ritz), 1, d, 1) call scopy(ncv, workl(ritz), 1, workl(ihd), 1) c end if c c %------------------------------------------------------------------% c | Transform the Ritz values and possibly vectors and corresponding | c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values | c | (and corresponding data) are returned in ascending order. | c %------------------------------------------------------------------% c if (type .eq. 'REGULR') then c c %---------------------------------------------------------% c | Ascending sort of wanted Ritz values, vectors and error | c | bounds. Not necessary if only Ritz values are desired. | c %---------------------------------------------------------% c if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) end if c else c c %-------------------------------------------------------------% c | * Make a copy of all the Ritz values. | c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | For TYPE = 'BUCKLE' the transformation is | c | lambda = sigma * theta / ( theta - 1 ) | c | For TYPE = 'CAYLEY' the transformation is | c | lambda = sigma * (theta + 1) / (theta - 1 ) | c | where the theta are the Ritz values returned by ssaupd. | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c | They are only reordered. | c %-------------------------------------------------------------% c call scopy (ncv, workl(ihd), 1, workl(iw), 1) if (type .eq. 'SHIFTI') then do 40 k=1, ncv workl(ihd+k-1) = one / workl(ihd+k-1) + sigma 40 continue else if (type .eq. 'BUCKLE') then do 50 k=1, ncv workl(ihd+k-1) = sigma * workl(ihd+k-1) / & (workl(ihd+k-1) - one) 50 continue else if (type .eq. 'CAYLEY') then do 60 k=1, ncv workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) / & (workl(ihd+k-1) - one) 60 continue end if c c %-------------------------------------------------------------% c | * Store the wanted NCONV lambda values into D. | c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) | c | into ascending order and apply sort to the NCONV theta | c | values in the transformed system. We will need this to | c | compute Ritz estimates in the original system. | c | * Finally sort the lambda`s into ascending order and apply | c | to Ritz vectors if wanted. Else just sort lambda`s into | c | ascending order. | c | NOTES: | c | *workl(iw:iw+ncv-1) contain the theta ordered so that they | c | match the ordering of the lambda. We`ll use them again for | c | Ritz vector purification. | c %-------------------------------------------------------------% c call scopy(nconv, workl(ihd), 1, d, 1) call ssortr('LA', .true., nconv, workl(ihd), workl(iw)) if (rvec) then call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq) else call scopy(ncv, workl(bounds), 1, workl(ihb), 1) call sscal(ncv, bnorm2/rnorm, workl(ihb), 1) call ssortr('LA', .true., nconv, d, workl(ihb)) end if c end if c c %------------------------------------------------% c | Compute the Ritz vectors. Transform the wanted | c | eigenvectors of the symmetric tridiagonal H by | c | the Lanczos basis matrix V. | c %------------------------------------------------% c if (rvec .and. howmny .eq. 'A') then c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(iq,ldq). | c %----------------------------------------------------------% c call sgeqr2(ncv, nconv , workl(iq) , & ldq, workl(iw+ncv), workl(ihb), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q. | c | * Copy the first NCONV columns of VQ into Z. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(ihd). | c %--------------------------------------------------------% c call sorm2r('Right', 'Notranspose', n , & ncv , nconv , workl(iq), & ldq , workl(iw+ncv), v , & ldv , workd(n+1) , ierr) call slacpy('All', n, nconv, v, ldv, z, ldz) c c %-----------------------------------------------------% c | In order to compute the Ritz estimates for the Ritz | c | values in both systems, need the last row of the | c | eigenvector matrix. Remember, it`s in factored form | c %-----------------------------------------------------% c do 65 j = 1, ncv-1 workl(ihb+j-1) = zero 65 continue workl(ihb+ncv-1) = one call sorm2r('Left', 'Transpose' , ncv , & 1 , nconv , workl(iq) , & ldq , workl(iw+ncv), workl(ihb), & ncv , temp , ierr) c c %-----------------------------------------------------% c | Make a copy of the last row into | c | workl(iw+ncv:iw+2*ncv), as it is needed again in | c | the Ritz vector purification step below | c %-----------------------------------------------------% c do 67 j = 1, nconv workl(iw+ncv+j-1) = workl(ihb+j-1) 67 continue else if (rvec .and. howmny .eq. 'S') then c c Not yet implemented. See remark 2 above. c end if c if (type .eq. 'REGULR' .and. rvec) then c do 70 j=1, ncv workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) ) 70 continue c else if (type .ne. 'REGULR' .and. rvec) then c c %-------------------------------------------------% c | * Determine Ritz estimates of the theta. | c | If RVEC = .true. then compute Ritz estimates | c | of the theta. | c | If RVEC = .false. then copy Ritz estimates | c | as computed by ssaupd. | c | * Determine Ritz estimates of the lambda. | c %-------------------------------------------------% c call sscal (ncv, bnorm2, workl(ihb), 1) if (type .eq. 'SHIFTI') then c do 80 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) ) & / workl(iw+k-1)**2 80 continue c else if (type .eq. 'BUCKLE') then c do 90 k=1, ncv workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) ) & / (workl(iw+k-1)-one )**2 90 continue c else if (type .eq. 'CAYLEY') then c do 100 k=1, ncv workl(ihb+k-1) = abs( workl(ihb+k-1) & / workl(iw+k-1)*(workl(iw+k-1)-one) ) 100 continue c end if c end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call svout(logfil, nconv, d, ndigit, & '_seupd: Untransformed converged Ritz values') call svout(logfil, nconv, workl(ihb), ndigit, & '_seupd: Ritz estimates of the untransformed Ritz values') else if (msglvl .gt. 1) then call svout(logfil, nconv, d, ndigit, & '_seupd: Converged Ritz values') call svout(logfil, nconv, workl(ihb), ndigit, & '_seupd: Associated Ritz estimates') end if c c %-------------------------------------------------% c | Ritz vector purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3,4,5. See reference 7 | c %-------------------------------------------------% c if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then c do 110 k=0, nconv-1 workl(iw+k) = workl(iw+ncv+k) & / workl(iw+k) 110 continue c else if (rvec .and. type .eq. 'BUCKLE') then c do 120 k=0, nconv-1 workl(iw+k) = workl(iw+ncv+k) & / (workl(iw+k)-one) 120 continue c end if c if (type .ne. 'REGULR') & call sger (n, nconv, one, resid, 1, workl(iw), 1, z, ldz) c 9000 continue c return c c %---------------% c | End of sseupd| c %---------------% c end arpack-ng-3.3.0/SRC/ssgets.f000066400000000000000000000163411260666001200154720ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssgets c c\Description: c Given the eigenvalues of the symmetric tridiagonal matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: This is called even in the case of user specified shifts in c order to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call ssgets c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> KEV eigenvalues of largest magnitude are retained. c 'SM' -> KEV eigenvalues of smallest magnitude are retained. c 'LA' -> KEV eigenvalues of largest value are retained. c 'SA' -> KEV eigenvalues of smallest value are retained. c 'BE' -> KEV eigenvalues, half from each end of the spectrum. c If KEV is odd, compute one more from the high end. c c KEV Integer. (INPUT) c KEV+NP is the size of the matrix H. c c NP Integer. (INPUT) c Number of implicit shifts to be computed. c c RITZ Real array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues c are in the first NP locations and the wanted part is in c the last KEV locations. When exact shifts are selected, the c unwanted part corresponds to the shifts to be applied. c c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c SHIFTS Real array of length NP. (INPUT/OUTPUT) c On INPUT: contains the user specified shifts if ISHIFT = 0. c On OUTPUT: contains the shifts sorted into decreasing order c of magnitude with respect to the Ritz estimates contained in c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c ssortr ARPACK utility sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c svout ARPACK utility routine that prints vectors. c scopy Level 1 BLAS that copies one vector to another. c sswap Level 1 BLAS that swaps the contents of two vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/93: Version ' 2.1' c c\SCCS Information: @(#) c FILE: sgets.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine ssgets ( ishift, which, kev, np, ritz, bounds, shifts ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Real & bounds(kev+np), ritz(kev+np), shifts(np) c c %------------% c | Parameters | c %------------% c Real & one, zero parameter (one = 1.0E+0, zero = 0.0E+0) c c %---------------% c | Local Scalars | c %---------------% c integer kevd2, msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external sswap, scopy, ssortr, arscnd c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic max, min c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = msgets c if (which .eq. 'BE') then c c %-----------------------------------------------------% c | Both ends of the spectrum are requested. | c | Sort the eigenvalues into algebraically increasing | c | order first then swap high end of the spectrum next | c | to low end in appropriate locations. | c | NOTE: when np < floor(kev/2) be careful not to swap | c | overlapping locations. | c %-----------------------------------------------------% c call ssortr ('LA', .true., kev+np, ritz, bounds) kevd2 = kev / 2 if ( kev .gt. 1 ) then call sswap ( min(kevd2,np), ritz, 1, & ritz( max(kevd2,np)+1 ), 1) call sswap ( min(kevd2,np), bounds, 1, & bounds( max(kevd2,np)+1 ), 1) end if c else c c %----------------------------------------------------% c | LM, SM, LA, SA case. | c | Sort the eigenvalues of H into the desired order | c | and apply the resulting order to BOUNDS. | c | The eigenvalues are sorted so that the wanted part | c | are always in the last KEV locations. | c %----------------------------------------------------% c call ssortr (which, .true., kev+np, ritz, bounds) end if c if (ishift .eq. 1 .and. np .gt. 0) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first. | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine ssapps. | c %-------------------------------------------------------% c call ssortr ('SM', .true., np, bounds, ritz) call scopy (np, ritz, 1, shifts, 1) end if c call arscnd (t1) tsgets = tsgets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_sgets: KEV is') call ivout (logfil, 1, np, ndigit, '_sgets: NP is') call svout (logfil, kev+np, ritz, ndigit, & '_sgets: Eigenvalues of current H matrix') call svout (logfil, kev+np, bounds, ndigit, & '_sgets: Associated Ritz estimates') end if c return c c %---------------% c | End of ssgets | c %---------------% c end arpack-ng-3.3.0/SRC/ssortc.f000066400000000000000000000217521260666001200155010ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssortc c c\Description: c Sorts the complex array in XREAL and XIMAG into the order c specified by WHICH and optionally applies the permutation to the c real array Y. It is assumed that if an element of XIMAG is c nonzero, then its negative is also an element. In other words, c both members of a complex conjugate pair are to be sorted and the c pairs are kept adjacent to each other. c c\Usage: c call ssortc c ( WHICH, APPLY, N, XREAL, XIMAG, Y ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> sort XREAL,XIMAG into increasing order of magnitude. c 'SM' -> sort XREAL,XIMAG into decreasing order of magnitude. c 'LR' -> sort XREAL into increasing order of algebraic. c 'SR' -> sort XREAL into decreasing order of algebraic. c 'LI' -> sort XIMAG into increasing order of magnitude. c 'SI' -> sort XIMAG into decreasing order of magnitude. c NOTE: If an element of XIMAG is non-zero, then its negative c is also an element. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to array Y. c APPLY = .FALSE. -> do not apply the sorted order to array Y. c c N Integer. (INPUT) c Size of the arrays. c c XREAL, Real array of length N. (INPUT/OUTPUT) c XIMAG Real and imaginary part of the array to be sorted. c c Y Real array of length N. (INPUT/OUTPUT) c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c xx/xx/92: Version ' 2.1' c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortc.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine ssortc (which, apply, n, xreal, ximag, y) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Real & xreal(0:n-1), ximag(0:n-1), y(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Real & temp, temp1, temp2 c c %--------------------% c | External Functions | c %--------------------% c Real & slapy2 external slapy2 c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'LM') then c c %------------------------------------------------------% c | Sort XREAL,XIMAG into increasing order of magnitude. | c %------------------------------------------------------% c 10 continue if (igap .eq. 0) go to 9000 c do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c temp1 = slapy2(xreal(j),ximag(j)) temp2 = slapy2(xreal(j+igap),ximag(j+igap)) c if (temp1.gt.temp2) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 30 end if j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c %------------------------------------------------------% c | Sort XREAL,XIMAG into decreasing order of magnitude. | c %------------------------------------------------------% c 40 continue if (igap .eq. 0) go to 9000 c do 60 i = igap, n-1 j = i-igap 50 continue c if (j .lt. 0) go to 60 c temp1 = slapy2(xreal(j),ximag(j)) temp2 = slapy2(xreal(j+igap),ximag(j+igap)) c if (temp1.lt.temp2) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LR') then c c %------------------------------------------------% c | Sort XREAL into increasing order of algebraic. | c %------------------------------------------------% c 70 continue if (igap .eq. 0) go to 9000 c do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (xreal(j).gt.xreal(j+igap)) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'SR') then c c %------------------------------------------------% c | Sort XREAL into decreasing order of algebraic. | c %------------------------------------------------% c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (xreal(j).lt.xreal(j+igap)) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 c else if (which .eq. 'LI') then c c %------------------------------------------------% c | Sort XIMAG into increasing order of magnitude. | c %------------------------------------------------% c 130 continue if (igap .eq. 0) go to 9000 do 150 i = igap, n-1 j = i-igap 140 continue c if (j.lt.0) go to 150 c if (abs(ximag(j)).gt.abs(ximag(j+igap))) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 150 endif j = j-igap go to 140 150 continue igap = igap / 2 go to 130 c else if (which .eq. 'SI') then c c %------------------------------------------------% c | Sort XIMAG into decreasing order of magnitude. | c %------------------------------------------------% c 160 continue if (igap .eq. 0) go to 9000 do 180 i = igap, n-1 j = i-igap 170 continue c if (j.lt.0) go to 180 c if (abs(ximag(j)).lt.abs(ximag(j+igap))) then temp = xreal(j) xreal(j) = xreal(j+igap) xreal(j+igap) = temp c temp = ximag(j) ximag(j) = ximag(j+igap) ximag(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 180 endif j = j-igap go to 170 180 continue igap = igap / 2 go to 160 end if c 9000 continue return c c %---------------% c | End of ssortc | c %---------------% c end arpack-ng-3.3.0/SRC/ssortr.f000066400000000000000000000122741260666001200155170ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: ssortr c c\Description: c Sort the array X1 in the order specified by WHICH and optionally c applies the permutation to the array X2. c c\Usage: c call ssortr c ( WHICH, APPLY, N, X1, X2 ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> X1 is sorted into increasing order of magnitude. c 'SM' -> X1 is sorted into decreasing order of magnitude. c 'LA' -> X1 is sorted into increasing order of algebraic. c 'SA' -> X1 is sorted into decreasing order of algebraic. c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to X2. c APPLY = .FALSE. -> do not apply the sorted order to X2. c c N Integer. (INPUT) c Size of the arrays. c c X1 Real array of length N. (INPUT/OUTPUT) c The array to be sorted. c c X2 Real array of length N. (INPUT/OUTPUT) c Only referenced if APPLY = .TRUE. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\Revision history: c 12/16/93: Version ' 2.1'. c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortr.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine ssortr (which, apply, n, x1, x2) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Real & x1(0:n-1), x2(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Real & temp c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'SA') then c c X1 is sorted into decreasing order of algebraic. c 10 continue if (igap .eq. 0) go to 9000 do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c if (x1(j).lt.x1(j+igap)) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 30 endif j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c X1 is sorted into decreasing order of magnitude. c 40 continue if (igap .eq. 0) go to 9000 do 60 i = igap, n-1 j = i-igap 50 continue c if (j.lt.0) go to 60 c if (abs(x1(j)).lt.abs(x1(j+igap))) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LA') then c c X1 is sorted into increasing order of algebraic. c 70 continue if (igap .eq. 0) go to 9000 do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (x1(j).gt.x1(j+igap)) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'LM') then c c X1 is sorted into increasing order of magnitude. c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (abs(x1(j)).gt.abs(x1(j+igap))) then temp = x1(j) x1(j) = x1(j+igap) x1(j+igap) = temp if (apply) then temp = x2(j) x2(j) = x2(j+igap) x2(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 end if c 9000 continue return c c %---------------% c | End of ssortr | c %---------------% c end arpack-ng-3.3.0/SRC/sstatn.f000066400000000000000000000027101260666001200154710ustar00rootroot00000000000000c c %---------------------------------------------% c | Initialize statistic and timing information | c | for nonsymmetric Arnoldi code. | c %---------------------------------------------% c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: statn.F SID: 2.4 DATE OF SID: 4/20/96 RELEASE: 2 c subroutine sstatn c c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c include 'stat.h' c c %-----------------------% c | Executable Statements | c %-----------------------% c nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 c tnaupd = 0.0E+0 tnaup2 = 0.0E+0 tnaitr = 0.0E+0 tneigh = 0.0E+0 tngets = 0.0E+0 tnapps = 0.0E+0 tnconv = 0.0E+0 titref = 0.0E+0 tgetv0 = 0.0E+0 trvec = 0.0E+0 c c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% c tmvopx = 0.0E+0 tmvbx = 0.0E+0 c return c c c %---------------% c | End of sstatn | c %---------------% c end arpack-ng-3.3.0/SRC/sstats.f000066400000000000000000000022161260666001200154770ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: stats.F SID: 2.1 DATE OF SID: 4/19/96 RELEASE: 2 c %---------------------------------------------% c | Initialize statistic and timing information | c | for symmetric Arnoldi code. | c %---------------------------------------------% subroutine sstats c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% include 'stat.h' c %-----------------------% c | Executable Statements | c %-----------------------% nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 tsaupd = 0.0E+0 tsaup2 = 0.0E+0 tsaitr = 0.0E+0 tseigt = 0.0E+0 tsgets = 0.0E+0 tsapps = 0.0E+0 tsconv = 0.0E+0 titref = 0.0E+0 tgetv0 = 0.0E+0 trvec = 0.0E+0 c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% tmvopx = 0.0E+0 tmvbx = 0.0E+0 return c c End of sstats c end arpack-ng-3.3.0/SRC/sstqrb.f000066400000000000000000000404641260666001200155030ustar00rootroot00000000000000c----------------------------------------------------------------------- c\BeginDoc c c\Name: sstqrb c c\Description: c Computes all eigenvalues and the last component of the eigenvectors c of a symmetric tridiagonal matrix using the implicit QL or QR method. c c This is mostly a modification of the LAPACK routine ssteqr. c See Remarks. c c\Usage: c call sstqrb c ( N, D, E, Z, WORK, INFO ) c c\Arguments c N Integer. (INPUT) c The number of rows and columns in the matrix. N >= 0. c c D Real array, dimension (N). (INPUT/OUTPUT) c On entry, D contains the diagonal elements of the c tridiagonal matrix. c On exit, D contains the eigenvalues, in ascending order. c If an error exit is made, the eigenvalues are correct c for indices 1,2,...,INFO-1, but they are unordered and c may not be the smallest eigenvalues of the matrix. c c E Real array, dimension (N-1). (INPUT/OUTPUT) c On entry, E contains the subdiagonal elements of the c tridiagonal matrix in positions 1 through N-1. c On exit, E has been destroyed. c c Z Real array, dimension (N). (OUTPUT) c On exit, Z contains the last row of the orthonormal c eigenvector matrix of the symmetric tridiagonal matrix. c If an error exit is made, Z contains the last row of the c eigenvector matrix associated with the stored eigenvalues. c c WORK Real array, dimension (max(1,2*N-2)). (WORKSPACE) c Workspace used in accumulating the transformation for c computing the last components of the eigenvectors. c c INFO Integer. (OUTPUT) c = 0: normal return. c < 0: if INFO = -i, the i-th argument had an illegal value. c > 0: if INFO = +i, the i-th eigenvalue has not converged c after a total of 30*N iterations. c c\Remarks c 1. None. c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx real c c\Routines called: c saxpy Level 1 BLAS that computes a vector triad. c scopy Level 1 BLAS that copies one vector to another. c sswap Level 1 BLAS that swaps the contents of two vectors. c lsame LAPACK character comparison routine. c slae2 LAPACK routine that computes the eigenvalues of a 2-by-2 c symmetric matrix. c slaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric c matrix. c slamch LAPACK routine that determines machine constants. c slanst LAPACK routine that computes the norm of a matrix. c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c slartg LAPACK Givens rotation construction routine. c slascl LAPACK routine for careful scaling of a matrix. c slaset LAPACK matrix initialization routine. c slasr LAPACK routine that applies an orthogonal transformation to c a matrix. c slasrt LAPACK sorting routine. c ssteqr LAPACK routine that computes eigenvalues and eigenvectors c of a symmetric tridiagonal matrix. c xerbla LAPACK error handler routine. c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c 1. Starting with version 2.5, this routine is a modified version c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted, c only commeted out and new lines inserted. c All lines commented out have "c$$$" at the beginning. c Note that the LAPACK version 1.0 subroutine SSTEQR contained c bugs. c c\EndLib c c----------------------------------------------------------------------- c subroutine sstqrb ( n, d, e, z, work, info ) c c %------------------% c | Scalar Arguments | c %------------------% c integer info, n c c %-----------------% c | Array Arguments | c %-----------------% c Real & d( n ), e( n-1 ), z( n ), work( 2*n-2 ) c c .. parameters .. Real & zero, one, two, three parameter ( zero = 0.0E+0, one = 1.0E+0, & two = 2.0E+0, three = 3.0E+0 ) integer maxit parameter ( maxit = 30 ) c .. c .. local scalars .. integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend, & lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1, & nm1, nmaxit Real & anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2, & s, safmax, safmin, ssfmax, ssfmin, tst c .. c .. external functions .. logical lsame Real & slamch, slanst, slapy2 external lsame, slamch, slanst, slapy2 c .. c .. external subroutines .. external slae2, slaev2, slartg, slascl, slaset, slasr, & slasrt, sswap, xerbla c .. c .. intrinsic functions .. intrinsic abs, max, sign, sqrt c .. c .. executable statements .. c c test the input parameters. c info = 0 c c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN c$$$ ICOMPZ = 0 c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN c$$$ ICOMPZ = 1 c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN c$$$ ICOMPZ = 2 c$$$ ELSE c$$$ ICOMPZ = -1 c$$$ END IF c$$$ IF( ICOMPZ.LT.0 ) THEN c$$$ INFO = -1 c$$$ ELSE IF( N.LT.0 ) THEN c$$$ INFO = -2 c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1, c$$$ $ N ) ) ) THEN c$$$ INFO = -6 c$$$ END IF c$$$ IF( INFO.NE.0 ) THEN c$$$ CALL XERBLA( 'SSTEQR', -INFO ) c$$$ RETURN c$$$ END IF c c *** New starting with version 2.5 *** c icompz = 2 c ************************************* c c quick return if possible c if( n.eq.0 ) $ return c if( n.eq.1 ) then if( icompz.eq.2 ) z( 1 ) = one return end if c c determine the unit roundoff and over/underflow thresholds. c eps = slamch( 'e' ) eps2 = eps**2 safmin = slamch( 's' ) safmax = one / safmin ssfmax = sqrt( safmax ) / three ssfmin = sqrt( safmin ) / eps2 c c compute the eigenvalues and eigenvectors of the tridiagonal c matrix. c c$$ if( icompz.eq.2 ) c$$$ $ call slaset( 'full', n, n, zero, one, z, ldz ) c c *** New starting with version 2.5 *** c if ( icompz .eq. 2 ) then do 5 j = 1, n-1 z(j) = zero 5 continue z( n ) = one end if c ************************************* c nmaxit = n*maxit jtot = 0 c c determine where the matrix splits and choose ql or qr iteration c for each block, according to whether top or bottom diagonal c element is smaller. c l1 = 1 nm1 = n - 1 c 10 continue if( l1.gt.n ) $ go to 160 if( l1.gt.1 ) $ e( l1-1 ) = zero if( l1.le.nm1 ) then do 20 m = l1, nm1 tst = abs( e( m ) ) if( tst.eq.zero ) $ go to 30 if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+ $ 1 ) ) ) )*eps ) then e( m ) = zero go to 30 end if 20 continue end if m = n c 30 continue l = l1 lsv = l lend = m lendsv = lend l1 = m + 1 if( lend.eq.l ) $ go to 10 c c scale submatrix in rows and columns l to lend c anorm = slanst( 'i', lend-l+1, d( l ), e( l ) ) iscale = 0 if( anorm.eq.zero ) $ go to 10 if( anorm.gt.ssfmax ) then iscale = 1 call slascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n, $ info ) call slascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n, $ info ) else if( anorm.lt.ssfmin ) then iscale = 2 call slascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n, $ info ) call slascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n, $ info ) end if c c choose between ql and qr iteration c if( abs( d( lend ) ).lt.abs( d( l ) ) ) then lend = lsv l = lendsv end if c if( lend.gt.l ) then c c ql iteration c c look for small subdiagonal element. c 40 continue if( l.ne.lend ) then lendm1 = lend - 1 do 50 m = l, lendm1 tst = abs( e( m ) )**2 if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+ $ safmin )go to 60 50 continue end if c m = lend c 60 continue if( m.lt.lend ) $ e( m ) = zero p = d( l ) if( m.eq.l ) $ go to 80 c c if remaining matrix is 2-by-2, use slae2 or slaev2 c to compute its eigensystem. c if( m.eq.l+1 ) then if( icompz.gt.0 ) then call slaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s ) work( l ) = c work( n-1+l ) = s c$$$ call slasr( 'r', 'v', 'b', n, 2, work( l ), c$$$ $ work( n-1+l ), z( 1, l ), ldz ) c c *** New starting with version 2.5 *** c tst = z(l+1) z(l+1) = c*tst - s*z(l) z(l) = s*tst + c*z(l) c ************************************* else call slae2( d( l ), e( l ), d( l+1 ), rt1, rt2 ) end if d( l ) = rt1 d( l+1 ) = rt2 e( l ) = zero l = l + 2 if( l.le.lend ) $ go to 40 go to 140 end if c if( jtot.eq.nmaxit ) $ go to 140 jtot = jtot + 1 c c form shift. c g = ( d( l+1 )-p ) / ( two*e( l ) ) r = slapy2( g, one ) g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) ) c s = one c = one p = zero c c inner loop c mm1 = m - 1 do 70 i = mm1, l, -1 f = s*e( i ) b = c*e( i ) call slartg( g, f, c, s, r ) if( i.ne.m-1 ) $ e( i+1 ) = r g = d( i+1 ) - p r = ( d( i )-g )*s + two*c*b p = s*r d( i+1 ) = g + p g = c*r - b c c if eigenvectors are desired, then save rotations. c if( icompz.gt.0 ) then work( i ) = c work( n-1+i ) = -s end if c 70 continue c c if eigenvectors are desired, then apply saved rotations. c if( icompz.gt.0 ) then mm = m - l + 1 c$$$ call slasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ), c$$$ $ z( 1, l ), ldz ) c c *** New starting with version 2.5 *** c call slasr( 'r', 'v', 'b', 1, mm, work( l ), & work( n-1+l ), z( l ), 1 ) c ************************************* end if c d( l ) = d( l ) - p e( l ) = g go to 40 c c eigenvalue found. c 80 continue d( l ) = p c l = l + 1 if( l.le.lend ) $ go to 40 go to 140 c else c c qr iteration c c look for small superdiagonal element. c 90 continue if( l.ne.lend ) then lendp1 = lend + 1 do 100 m = l, lendp1, -1 tst = abs( e( m-1 ) )**2 if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+ $ safmin )go to 110 100 continue end if c m = lend c 110 continue if( m.gt.lend ) $ e( m-1 ) = zero p = d( l ) if( m.eq.l ) $ go to 130 c c if remaining matrix is 2-by-2, use slae2 or slaev2 c to compute its eigensystem. c if( m.eq.l-1 ) then if( icompz.gt.0 ) then call slaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s ) c$$$ work( m ) = c c$$$ work( n-1+m ) = s c$$$ call slasr( 'r', 'v', 'f', n, 2, work( m ), c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz ) c c *** New starting with version 2.5 *** c tst = z(l) z(l) = c*tst - s*z(l-1) z(l-1) = s*tst + c*z(l-1) c ************************************* else call slae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 ) end if d( l-1 ) = rt1 d( l ) = rt2 e( l-1 ) = zero l = l - 2 if( l.ge.lend ) $ go to 90 go to 140 end if c if( jtot.eq.nmaxit ) $ go to 140 jtot = jtot + 1 c c form shift. c g = ( d( l-1 )-p ) / ( two*e( l-1 ) ) r = slapy2( g, one ) g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) ) c s = one c = one p = zero c c inner loop c lm1 = l - 1 do 120 i = m, lm1 f = s*e( i ) b = c*e( i ) call slartg( g, f, c, s, r ) if( i.ne.m ) $ e( i-1 ) = r g = d( i ) - p r = ( d( i+1 )-g )*s + two*c*b p = s*r d( i ) = g + p g = c*r - b c c if eigenvectors are desired, then save rotations. c if( icompz.gt.0 ) then work( i ) = c work( n-1+i ) = s end if c 120 continue c c if eigenvectors are desired, then apply saved rotations. c if( icompz.gt.0 ) then mm = l - m + 1 c$$$ call slasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ), c$$$ $ z( 1, m ), ldz ) c c *** New starting with version 2.5 *** c call slasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ), & z( m ), 1 ) c ************************************* end if c d( l ) = d( l ) - p e( lm1 ) = g go to 90 c c eigenvalue found. c 130 continue d( l ) = p c l = l - 1 if( l.ge.lend ) $ go to 90 go to 140 c end if c c undo scaling if necessary c 140 continue if( iscale.eq.1 ) then call slascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, $ d( lsv ), n, info ) call slascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ), $ n, info ) else if( iscale.eq.2 ) then call slascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, $ d( lsv ), n, info ) call slascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ), $ n, info ) end if c c check for no convergence to an eigenvalue after a total c of n*maxit iterations. c if( jtot.lt.nmaxit ) $ go to 10 do 150 i = 1, n - 1 if( e( i ).ne.zero ) $ info = info + 1 150 continue go to 190 c c order eigenvalues and eigenvectors. c 160 continue if( icompz.eq.0 ) then c c use quick sort c call slasrt( 'i', n, d, info ) c else c c use selection sort to minimize swaps of eigenvectors c do 180 ii = 2, n i = ii - 1 k = i p = d( i ) do 170 j = ii, n if( d( j ).lt.p ) then k = j p = d( j ) end if 170 continue if( k.ne.i ) then d( k ) = d( i ) d( i ) = p c$$$ call sswap( n, z( 1, i ), 1, z( 1, k ), 1 ) c *** New starting with version 2.5 *** c p = z(k) z(k) = z(i) z(i) = p c ************************************* end if 180 continue end if c 190 continue return c c %---------------% c | End of sstqrb | c %---------------% c end arpack-ng-3.3.0/SRC/stat.h000066400000000000000000000017131260666001200151340ustar00rootroot00000000000000c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c c\SCCS Information: @(#) c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2 c real t0, t1, t2, t3, t4, t5 save t0, t1, t2, t3, t4, t5 c integer nopx, nbx, nrorth, nitref, nrstrt real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec common /timing/ & nopx, nbx, nrorth, nitref, nrstrt, & tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv, & tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv, & tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv, & tmvopx, tmvbx, tgetv0, titref, trvec arpack-ng-3.3.0/SRC/version.h000066400000000000000000000023461260666001200156510ustar00rootroot00000000000000/* In the current version, the parameter KAPPA in the Kahan's test for orthogonality is set to 0.717, the same as used by Gragg & Reichel. However computational experience indicates that this is a little too strict and will frequently force reorthogonalization when it is not necessary to do so. Also the "moving boundary" idea is not currently activated in the nonsymmetric code since it is not conclusive that it's the right thing to do all the time. Requires further investigation. As of 02/01/93 Richard Lehoucq assumes software control of the codes from Phuong Vu. On 03/01/93 all the *.F files were migrated SCCS. The 1.1 version of codes are those received from Phuong Vu. The frozen version of 07/08/92 is now considered version 1.1. Version 2.1 contains two new symmetric routines, sesrt and seupd. Changes as well as bug fixes for version 1.1 codes that were only corrected for programming bugs are version 1.2. These 1.2 versions will also be in version 2.1. Subroutine [d,s]saupd now requires slightly more workspace. See [d,s]saupd for the details. \SCCS Information: @(#) FILE: version.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 */ #define VERSION_NUMBER ' 2.1' #define VERSION_DATE ' 11/15/95' arpack-ng-3.3.0/SRC/zgetv0.f000066400000000000000000000312741260666001200154030ustar00rootroot00000000000000c\BeginDoc c c\Name: zgetv0 c c\Description: c Generate a random initial residual vector for the Arnoldi process. c Force the residual vector to be in the range of the operator OP. c c\Usage: c call zgetv0 c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM, c IPNTR, WORKD, IERR ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to zgetv0. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 99: done c ------------------------------------------------------------- c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B in the (generalized) c eigenvalue problem A*x = lambda*B*x. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x c c ITRY Integer. (INPUT) c ITRY counts the number of times that zgetv0 is called. c It should be set to 1 on the initial call to zgetv0. c c INITV Logical variable. (INPUT) c .TRUE. => the initial residual vector is given in RESID. c .FALSE. => generate a random initial residual vector. c c N Integer. (INPUT) c Dimension of the problem. c c J Integer. (INPUT) c Index of the residual vector to be generated, with respect to c the Arnoldi process. J > 1 in case of a "restart". c c V Complex*16 N by J array. (INPUT) c The first J-1 columns of V contain the current Arnoldi basis c if this is a "restart". c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c Initial residual vector to be generated. If RESID is c provided, force RESID into the range of the operator OP. c c RNORM Double precision scalar. (OUTPUT) c B-norm of the generated residual. c c IPNTR Integer array of length 3. (OUTPUT) c c WORKD Complex*16 work array of length 2*N. (REVERSE COMMUNICATION). c On exit, WORK(1:N) = B*RESID to be used in SSAITR. c c IERR Integer. (OUTPUT) c = 0: Normal exit. c = -1: Cannot generate a nontrivial restarted residual vector c in the range of the operator OP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c arscnd ARPACK utility routine for timing. c zvout ARPACK utility routine that prints vectors. c zlarnv LAPACK routine for generating a random vector. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zcopy Level 1 BLAS that copies one vector to another. c zdotc Level 1 BLAS that computes the scalar product of two vectors. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: getv0.F SID: 2.3 DATE OF SID: 08/27/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine zgetv0 & ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm, & ipntr, workd, ierr ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 logical initv integer ido, ierr, itry, j, ldv, n Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & resid(n), v(ldv,j), workd(2*n) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0), & rzero = 0.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical first, inits, orth integer idist, iseed(4), iter, msglvl, jj Double precision & rnorm0 Complex*16 & cnorm save first, iseed, inits, iter, msglvl, orth, rnorm0 c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy, zgemv, zlarnv, zvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2, dlapy2 Complex*16 & zdotc external zdotc, dznrm2, dlapy2 c c %-----------------% c | Data Statements | c %-----------------% c data inits /.true./ c c %-----------------------% c | Executable Statements | c %-----------------------% c c c %-----------------------------------% c | Initialize the seed of the LAPACK | c | random number generator | c %-----------------------------------% c if (inits) then iseed(1) = 1 iseed(2) = 3 iseed(3) = 5 iseed(4) = 7 inits = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mgetv0 c ierr = 0 iter = 0 first = .FALSE. orth = .FALSE. c c %-----------------------------------------------------% c | Possibly generate a random starting vector in RESID | c | Use a LAPACK random number generator used by the | c | matrix generation routines. | c | idist = 1: uniform (0,1) distribution; | c | idist = 2: uniform (-1,1) distribution; | c | idist = 3: normal (0,1) distribution; | c %-----------------------------------------------------% c if (.not.initv) then idist = 2 call zlarnv (idist, iseed, n, resid) end if c c %----------------------------------------------------------% c | Force the starting vector into the range of OP to handle | c | the generalized problem when B is possibly (singular). | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nopx = nopx + 1 ipntr(1) = 1 ipntr(2) = n + 1 call zcopy (n, resid, 1, workd, 1) ido = -1 go to 9000 end if end if c c %----------------------------------------% c | Back from computing B*(initial-vector) | c %----------------------------------------% c if (first) go to 20 c c %-----------------------------------------------% c | Back from computing B*(orthogonalized-vector) | c %-----------------------------------------------% c if (orth) go to 40 c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) c c %------------------------------------------------------% c | Starting vector is now in the range of OP; r = OP*r; | c | Compute B-norm of starting vector. | c %------------------------------------------------------% c call arscnd (t2) first = .TRUE. if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, workd(n+1), 1, resid, 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 20 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c first = .FALSE. if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd, 1) rnorm0 = sqrt(dlapy2(dble(cnorm),dimag(cnorm))) else if (bmat .eq. 'I') then rnorm0 = dznrm2(n, resid, 1) end if rnorm = rnorm0 c c %---------------------------------------------% c | Exit if this is the very first Arnoldi step | c %---------------------------------------------% c if (j .eq. 1) go to 50 c c %---------------------------------------------------------------- c | Otherwise need to B-orthogonalize the starting vector against | c | the current Arnoldi basis using Gram-Schmidt with iter. ref. | c | This is the case where an invariant subspace is encountered | c | in the middle of the Arnoldi factorization. | c | | c | s = V^{T}*B*r; r = r - V*s; | c | | c | Stopping criteria used for iter. ref. is discussed in | c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. | c %---------------------------------------------------------------% c orth = .TRUE. 30 continue c call zgemv ('C', n, j-1, one, v, ldv, workd, 1, & zero, workd(n+1), 1) call zgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1, & one, resid, 1) c c %----------------------------------------------------------% c | Compute the B-norm of the orthogonalized starting vector | c %----------------------------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 40 continue c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd, 1) rnorm = sqrt(dlapy2(dble(cnorm),dimag(cnorm))) else if (bmat .eq. 'I') then rnorm = dznrm2(n, resid, 1) end if c c %--------------------------------------% c | Check for further orthogonalization. | c %--------------------------------------% c if (msglvl .gt. 2) then call dvout (logfil, 1, rnorm0, ndigit, & '_getv0: re-orthonalization ; rnorm0 is') call dvout (logfil, 1, rnorm, ndigit, & '_getv0: re-orthonalization ; rnorm is') end if c if (rnorm .gt. 0.717*rnorm0) go to 50 c iter = iter + 1 if (iter .le. 1) then c c %-----------------------------------% c | Perform iterative refinement step | c %-----------------------------------% c rnorm0 = rnorm go to 30 else c c %------------------------------------% c | Iterative refinement step "failed" | c %------------------------------------% c do 45 jj = 1, n resid(jj) = zero 45 continue rnorm = rzero ierr = -1 end if c 50 continue c if (msglvl .gt. 0) then call dvout (logfil, 1, rnorm, ndigit, & '_getv0: B-norm of initial / restarted starting vector') end if if (msglvl .gt. 2) then call zvout (logfil, n, resid, ndigit, & '_getv0: initial / restarted starting vector') end if ido = 99 c call arscnd (t1) tgetv0 = tgetv0 + (t1 - t0) c 9000 continue return c c %---------------% c | End of zgetv0 | c %---------------% c end arpack-ng-3.3.0/SRC/znaitr.f000066400000000000000000000746331260666001200155010ustar00rootroot00000000000000c\BeginDoc c c\Name: znaitr c c\Description: c Reverse communication interface for applying NP additional steps to c a K step nonsymmetric Arnoldi factorization. c c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T c c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0. c c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T c c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0. c c where OP and B are as in znaupd. The B-norm of r_{k+p} is also c computed and returned. c c\Usage: c call znaitr c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH, c IPNTR, WORKD, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c This is for the restart phase to force the new c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y, c IPNTR(3) is the pointer into WORK for B * X. c IDO = 2: compute Y = B * X where c IPNTR(1) is the pointer into WORK for X, c IPNTR(2) is the pointer into WORK for Y. c IDO = 99: done c ------------------------------------------------------------- c When the routine is used in the "shift-and-invert" mode, the c vector B * Q is already available and do not need to be c recomputed in forming OP * Q. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. See znaupd. c B = 'I' -> standard eigenvalue problem A*x = lambda*x c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c K Integer. (INPUT) c Current size of V and H. c c NP Integer. (INPUT) c Number of additional Arnoldi steps to take. c c NB Integer. (INPUT) c Blocksize to be used in the recurrence. c Only work for NB = 1 right now. The goal is to have a c program that implement both the block and non-block method. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: RESID contains the residual vector r_{k}. c On OUTPUT: RESID contains the residual vector r_{k+p}. c c RNORM Double precision scalar. (INPUT/OUTPUT) c B-norm of the starting residual on input. c B-norm of the updated residual r_{k+p} on output. c c V Complex*16 N by K+NP array. (INPUT/OUTPUT) c On INPUT: V contains the Arnoldi vectors in the first K c columns. c On OUTPUT: V contains the new NP Arnoldi vectors in the next c NP columns. The first K columns are unchanged. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (K+NP) by (K+NP) array. (INPUT/OUTPUT) c H is used to store the generated upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORK for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The calling program should not c use WORKD as temporary workspace during the iteration !!!!!! c On input, WORKD(1:N) = B*RESID and is used to save some c computation at the first step. c c INFO Integer. (OUTPUT) c = 0: Normal exit. c > 0: Size of the spanning invariant subspace of OP found. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c zgetv0 ARPACK routine to generate the initial vector. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c zmout ARPACK utility routine that prints matrices c zvout ARPACK utility routine that prints vectors. c zlanhs LAPACK routine that computes various norms of a matrix. c zlascl LAPACK routine for careful scaling of a matrix. c dlabad LAPACK routine for defining the underflow and overflow c limits. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of two vectors. c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naitr.F SID: 2.3 DATE OF SID: 8/27/96 RELEASE: 2 c c\Remarks c The algorithm implemented is: c c restart = .false. c Given V_{k} = [v_{1}, ..., v_{k}], r_{k}; c r_{k} contains the initial residual vector even for k = 0; c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already c computed by the calling program. c c betaj = rnorm ; p_{k+1} = B*r_{k} ; c For j = k+1, ..., k+np Do c 1) if ( betaj < tol ) stop or restart depending on j. c ( At present tol is zero ) c if ( restart ) generate a new starting vector. c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}]; c p_{j} = p_{j}/betaj c 3) r_{j} = OP*v_{j} where OP is defined as in znaupd c For shift-invert mode p_{j} = B*v_{j} is already available. c wnorm = || OP*v_{j} || c 4) Compute the j-th step residual vector. c w_{j} = V_{j}^T * B * OP * v_{j} c r_{j} = OP*v_{j} - V_{j} * w_{j} c H(:,j) = w_{j}; c H(j,j-1) = rnorm c rnorm = || r_(j) || c If (rnorm > 0.717*wnorm) accept step and go back to 1) c 5) Re-orthogonalization step: c s = V_{j}'*B*r_{j} c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} || c alphaj = alphaj + s_{j}; c 6) Iterative refinement step: c If (rnorm1 > 0.717*rnorm) then c rnorm = rnorm1 c accept step and go back to 1) c Else c rnorm = rnorm1 c If this is the first time in step 6), go to 5) c Else r_{j} lies in the span of V_{j} numerically. c Set r_{j} = 0 and rnorm = 0; go to 1) c EndIf c End Do c c\EndLib c c----------------------------------------------------------------------- c subroutine znaitr & (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh, & ipntr, workd, info) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1 integer ido, info, k, ldh, ldv, n, nb, np Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(3) Complex*16 & h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone, rzero parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0), & rone = 1.0D+0, rzero = 0.0D+0) c c %--------------% c | Local Arrays | c %--------------% c Double precision & rtemp(2) c c %---------------% c | Local Scalars | c %---------------% c logical first, orth1, orth2, rstart, step3, step4 integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl, & jj Double precision & ovfl, smlnum, tst1, ulp, unfl, betaj, & temp1, rnorm1, wnorm Complex*16 & cnorm c save first, orth1, orth2, rstart, step3, step4, & ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl, & betaj, rnorm1, smlnum, ulp, unfl, wnorm c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zscal, zdscal, zgemv, zgetv0, & dlabad, zvout, zmout, ivout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Complex*16 & zdotc Double precision & dlamch, dznrm2, zlanhs, dlapy2 external zdotc, dznrm2, zlanhs, dlamch, dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag, dble, max, sqrt c c %-----------------% c | Data statements | c %-----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------% c | Set machine-dependent constants for the | c | the splitting and deflation criterion. | c | If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------% c unfl = dlamch( 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = dlamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcaitr c c %------------------------------% c | Initial call to this routine | c %------------------------------% c info = 0 step3 = .false. step4 = .false. rstart = .false. orth1 = .false. orth2 = .false. j = k + 1 ipj = 1 irj = ipj + n ivj = irj + n end if c c %-------------------------------------------------% c | When in reverse communication mode one of: | c | STEP3, STEP4, ORTH1, ORTH2, RSTART | c | will be .true. when .... | c | STEP3: return from computing OP*v_{j}. | c | STEP4: return from computing B-norm of OP*v_{j} | c | ORTH1: return from computing B-norm of r_{j+1} | c | ORTH2: return from computing B-norm of | c | correction to the residual vector. | c | RSTART: return from OP computations needed by | c | zgetv0. | c %-------------------------------------------------% c if (step3) go to 50 if (step4) go to 60 if (orth1) go to 70 if (orth2) go to 90 if (rstart) go to 30 c c %-----------------------------% c | Else this is the first step | c %-----------------------------% c c %--------------------------------------------------------------% c | | c | A R N O L D I I T E R A T I O N L O O P | c | | c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) | c %--------------------------------------------------------------% 1000 continue c if (msglvl .gt. 1) then call ivout (logfil, 1, j, ndigit, & '_naitr: generating Arnoldi vector number') call dvout (logfil, 1, rnorm, ndigit, & '_naitr: B-norm of the current residual is') end if c c %---------------------------------------------------% c | STEP 1: Check if the B norm of j-th residual | c | vector is zero. Equivalent to determine whether | c | an exact j-step Arnoldi factorization is present. | c %---------------------------------------------------% c betaj = rnorm if (rnorm .gt. rzero) go to 40 c c %---------------------------------------------------% c | Invariant subspace found, generate a new starting | c | vector which is orthogonal to the current Arnoldi | c | basis and continue the iteration. | c %---------------------------------------------------% c if (msglvl .gt. 0) then call ivout (logfil, 1, j, ndigit, & '_naitr: ****** RESTART AT STEP ******') end if c c %---------------------------------------------% c | ITRY is the loop variable that controls the | c | maximum amount of times that a restart is | c | attempted. NRSTRT is used by stat.h | c %---------------------------------------------% c betaj = rzero nrstrt = nrstrt + 1 itry = 1 20 continue rstart = .true. ido = 0 30 continue c c %--------------------------------------% c | If in reverse communication mode and | c | RSTART = .true. flow returns here. | c %--------------------------------------% c call zgetv0 (ido, bmat, itry, .false., n, j, v, ldv, & resid, rnorm, ipntr, workd, ierr) if (ido .ne. 99) go to 9000 if (ierr .lt. 0) then itry = itry + 1 if (itry .le. 3) go to 20 c c %------------------------------------------------% c | Give up after several restart attempts. | c | Set INFO to the size of the invariant subspace | c | which spans OP and exit. | c %------------------------------------------------% c info = j - 1 call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 go to 9000 end if c 40 continue c c %---------------------------------------------------------% c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm | c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow | c | when reciprocating a small RNORM, test against lower | c | machine bound. | c %---------------------------------------------------------% c call zcopy (n, resid, 1, v(1,j), 1) if ( rnorm .ge. unfl) then temp1 = rone / rnorm call zdscal (n, temp1, v(1,j), 1) call zdscal (n, temp1, workd(ipj), 1) else c c %-----------------------------------------% c | To scale both v_{j} and p_{j} carefully | c | use LAPACK routine zlascl | c %-----------------------------------------% c call zlascl ('General', i, i, rnorm, rone, & n, 1, v(1,j), n, infol) call zlascl ('General', i, i, rnorm, rone, & n, 1, workd(ipj), n, infol) end if c c %------------------------------------------------------% c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} | c | Note that this is not quite yet r_{j}. See STEP 4 | c %------------------------------------------------------% c step3 = .true. nopx = nopx + 1 call arscnd (t2) call zcopy (n, v(1,j), 1, workd(ivj), 1) ipntr(1) = ivj ipntr(2) = irj ipntr(3) = ipj ido = 1 c c %-----------------------------------% c | Exit in order to compute OP*v_{j} | c %-----------------------------------% c go to 9000 50 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} | c | if step3 = .true. | c %----------------------------------% c call arscnd (t3) tmvopx = tmvopx + (t3 - t2) step3 = .false. c c %------------------------------------------% c | Put another copy of OP*v_{j} into RESID. | c %------------------------------------------% c call zcopy (n, workd(irj), 1, resid, 1) c c %---------------------------------------% c | STEP 4: Finish extending the Arnoldi | c | factorization to length j. | c %---------------------------------------% c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 step4 = .true. ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-------------------------------------% c | Exit in order to compute B*OP*v_{j} | c %-------------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 60 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} | c | if step4 = .true. | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c step4 = .false. c c %-------------------------------------% c | The following is needed for STEP 5. | c | Compute the B-norm of OP*v_{j}. | c %-------------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) wnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then wnorm = dznrm2(n, resid, 1) end if c c %-----------------------------------------% c | Compute the j-th residual corresponding | c | to the j step factorization. | c | Use Classical Gram Schmidt and compute: | c | w_{j} <- V_{j}^T * B * OP * v_{j} | c | r_{j} <- OP*v_{j} - V_{j} * w_{j} | c %-----------------------------------------% c c c %------------------------------------------% c | Compute the j Fourier coefficients w_{j} | c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. | c %------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, h(1,j), 1) c c %--------------------------------------% c | Orthogonalize r_{j} against V_{j}. | c | RESID contains OP*v_{j}. See STEP 3. | c %--------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, h(1,j), 1, & one, resid, 1) c if (j .gt. 1) h(j,j-1) = dcmplx(betaj, rzero) c call arscnd (t4) c orth1 = .true. c call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %----------------------------------% c | Exit in order to compute B*r_{j} | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 70 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH1 = .true. | c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c orth1 = .false. c c %------------------------------% c | Compute the B-norm of r_{j}. | c %------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) rnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm = dznrm2(n, resid, 1) end if c c %-----------------------------------------------------------% c | STEP 5: Re-orthogonalization / Iterative refinement phase | c | Maximum NITER_ITREF tries. | c | | c | s = V_{j}^T * B * r_{j} | c | r_{j} = r_{j} - V_{j}*s | c | alphaj = alphaj + s_{j} | c | | c | The stopping criteria used for iterative refinement is | c | discussed in Parlett's book SEP, page 107 and in Gragg & | c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. | c | Determine if we need to correct the residual. The goal is | c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || | c | The following test determines whether the sine of the | c | angle between OP*x and the computed residual is less | c | than or equal to 0.717. | c %-----------------------------------------------------------% c if ( rnorm .gt. 0.717*wnorm ) go to 100 c iter = 0 nrorth = nrorth + 1 c c %---------------------------------------------------% c | Enter the Iterative refinement phase. If further | c | refinement is necessary, loop back here. The loop | c | variable is ITER. Perform a step of Classical | c | Gram-Schmidt using all the Arnoldi vectors V_{j} | c %---------------------------------------------------% c 80 continue c if (msglvl .gt. 2) then rtemp(1) = wnorm rtemp(2) = rnorm call dvout (logfil, 2, rtemp, ndigit, & '_naitr: re-orthogonalization; wnorm and rnorm are') call zvout (logfil, j, h(1,j), ndigit, & '_naitr: j-th column of H') end if c c %----------------------------------------------------% c | Compute V_{j}^T * B * r_{j}. | c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). | c %----------------------------------------------------% c call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1, & zero, workd(irj), 1) c c %---------------------------------------------% c | Compute the correction to the residual: | c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). | c | The correction to H is v(:,1:J)*H(1:J,1:J) | c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. | c %---------------------------------------------% c call zgemv ('N', n, j, -one, v, ldv, workd(irj), 1, & one, resid, 1) call zaxpy (j, one, workd(irj), 1, h(1,j), 1) c orth2 = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(irj), 1) ipntr(1) = irj ipntr(2) = ipj ido = 2 c c %-----------------------------------% c | Exit in order to compute B*r_{j}. | c | r_{j} is the corrected residual. | c %-----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd(ipj), 1) end if 90 continue c c %---------------------------------------------------% c | Back from reverse communication if ORTH2 = .true. | c %---------------------------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c c %-----------------------------------------------------% c | Compute the B-norm of the corrected residual r_{j}. | c %-----------------------------------------------------% c if (bmat .eq. 'G') then cnorm = zdotc (n, resid, 1, workd(ipj), 1) rnorm1 = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) ) else if (bmat .eq. 'I') then rnorm1 = dznrm2(n, resid, 1) end if c if (msglvl .gt. 0 .and. iter .gt. 0 ) then call ivout (logfil, 1, j, ndigit, & '_naitr: Iterative refinement for Arnoldi residual') if (msglvl .gt. 2) then rtemp(1) = rnorm rtemp(2) = rnorm1 call dvout (logfil, 2, rtemp, ndigit, & '_naitr: iterative refinement ; rnorm and rnorm1 are') end if end if c c %-----------------------------------------% c | Determine if we need to perform another | c | step of re-orthogonalization. | c %-----------------------------------------% c if ( rnorm1 .gt. 0.717*rnorm ) then c c %---------------------------------------% c | No need for further refinement. | c | The cosine of the angle between the | c | corrected residual vector and the old | c | residual vector is greater than 0.717 | c | In other words the corrected residual | c | and the old residual vector share an | c | angle of less than arcCOS(0.717) | c %---------------------------------------% c rnorm = rnorm1 c else c c %-------------------------------------------% c | Another step of iterative refinement step | c | is required. NITREF is used by stat.h | c %-------------------------------------------% c nitref = nitref + 1 rnorm = rnorm1 iter = iter + 1 if (iter .le. 1) go to 80 c c %-------------------------------------------------% c | Otherwise RESID is numerically in the span of V | c %-------------------------------------------------% c do 95 jj = 1, n resid(jj) = zero 95 continue rnorm = rzero end if c c %----------------------------------------------% c | Branch here directly if iterative refinement | c | wasn't necessary or after at most NITER_REF | c | steps of iterative refinement. | c %----------------------------------------------% c 100 continue c rstart = .false. orth2 = .false. c call arscnd (t5) titref = titref + (t5 - t4) c c %------------------------------------% c | STEP 6: Update j = j+1; Continue | c %------------------------------------% c j = j + 1 if (j .gt. k+np) then call arscnd (t1) tcaitr = tcaitr + (t1 - t0) ido = 99 do 110 i = max(1,k), k+np-1 c c %--------------------------------------------% c | Check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %--------------------------------------------% c tst1 = dlapy2(dble(h(i,i)),dimag(h(i,i))) & + dlapy2(dble(h(i+1,i+1)), dimag(h(i+1,i+1))) if( tst1.eq.dble(zero) ) & tst1 = zlanhs( '1', k+np, h, ldh, workd(n+1) ) if( dlapy2(dble(h(i+1,i)),dimag(h(i+1,i))) .le. & max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 110 continue c if (msglvl .gt. 2) then call zmout (logfil, k+np, k+np, h, ldh, ndigit, & '_naitr: Final upper Hessenberg matrix H of order K+NP') end if c go to 9000 end if c c %--------------------------------------------------------% c | Loop back to extend the factorization by another step. | c %--------------------------------------------------------% c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 9000 continue return c c %---------------% c | End of znaitr | c %---------------% c end arpack-ng-3.3.0/SRC/znapps.f000066400000000000000000000423311260666001200154730ustar00rootroot00000000000000c\BeginDoc c c\Name: znapps c c\Description: c Given the Arnoldi factorization c c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T, c c apply NP implicit shifts resulting in c c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q c c where Q is an orthogonal matrix which is the product of rotations c and reflections resulting from the NP bulge change sweeps. c The updated Arnoldi factorization becomes: c c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T. c c\Usage: c call znapps c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, c WORKL, WORKD ) c c\Arguments c N Integer. (INPUT) c Problem size, i.e. size of matrix A. c c KEV Integer. (INPUT/OUTPUT) c KEV+NP is the size of the input matrix H. c KEV is the size of the updated matrix HNEW. c c NP Integer. (INPUT) c Number of implicit shifts to be applied. c c SHIFT Complex*16 array of length NP. (INPUT) c The shifts to be applied. c c V Complex*16 N by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, V contains the current KEV+NP Arnoldi vectors. c On OUTPUT, V contains the updated KEV Arnoldi vectors c in the first KEV columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT) c On INPUT, H contains the current KEV+NP by KEV+NP upper c Hessenberg matrix of the Arnoldi factorization. c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg c matrix in the KEV leading submatrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT, RESID contains the the residual vector r_{k+p}. c On OUTPUT, RESID is the update residual vector rnew_{k} c in the first KEV locations. c c Q Complex*16 KEV+NP by KEV+NP work array. (WORKSPACE) c Work array used to accumulate the rotations and reflections c during the bulge chase sweep. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length (KEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c WORKD Complex*16 work array of length 2*N. (WORKSPACE) c Distributed array used in the application of the accumulated c orthogonal matrix Q. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c zmout ARPACK utility routine that prints matrices c zvout ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlanhs LAPACK routine that computes various norms of a matrix. c zlartg LAPACK Givens rotation construction routine. c zlaset LAPACK matrix initialization routine. c dlabad LAPACK routine for defining the underflow and overflow c limits. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zgemv Level 2 BLAS routine for matrix vector multiplication. c zaxpy Level 1 BLAS that computes a vector triad. c zcopy Level 1 BLAS that copies one vector to another. c zscal Level 1 BLAS that scales a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: napps.F SID: 2.3 DATE OF SID: 3/28/97 RELEASE: 2 c c\Remarks c 1. In this version, each shift is applied to all the sublocks of c the Hessenberg matrix H and not just to the submatrix that it c comes from. Deflation as in LAPACK routine zlahqr (QR algorithm c for upper Hessenberg matrices ) is used. c Upon output, the subdiagonals of H are enforced to be non-negative c real numbers. c c\EndLib c c----------------------------------------------------------------------- c subroutine znapps & ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, & workl, workd ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer kev, ldh, ldq, ldv, n, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & h(ldh,kev+np), resid(n), shift(np), & v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0), & rzero = 0.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c integer i, iend, istart, j, jj, kplusp, msglvl logical first Complex*16 & cdum, f, g, h11, h21, r, s, sigma, t Double precision & c, ovfl, smlnum, ulp, unfl, tst1 save first, ovfl, smlnum, ulp, unfl c c %----------------------% c | External Subroutines | c %----------------------% c external zaxpy, zcopy, zgemv, zscal, zlacpy, zlartg, & zvout, zlaset, dlabad, zmout, arscnd, ivout c c %--------------------% c | External Functions | c %--------------------% c Double precision & zlanhs, dlamch, dlapy2 external zlanhs, dlamch, dlapy2 c c %----------------------% c | Intrinsics Functions | c %----------------------% c intrinsic abs, dimag, conjg, dcmplx, max, min, dble c c %---------------------% c | Statement Functions | c %---------------------% c Double precision & zabs1 zabs1( cdum ) = abs( dble( cdum ) ) + abs( dimag( cdum ) ) c c %----------------% c | Data statments | c %----------------% c data first / .true. / c c %-----------------------% c | Executable Statements | c %-----------------------% c if (first) then c c %-----------------------------------------------% c | Set machine-dependent constants for the | c | stopping criterion. If norm(H) <= sqrt(OVFL), | c | overflow should not occur. | c | REFERENCE: LAPACK subroutine zlahqr | c %-----------------------------------------------% c unfl = dlamch( 'safe minimum' ) ovfl = dble(one / unfl) call dlabad( unfl, ovfl ) ulp = dlamch( 'precision' ) smlnum = unfl*( n / ulp ) first = .false. end if c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcapps c kplusp = kev + np c c %--------------------------------------------% c | Initialize Q to the identity to accumulate | c | the rotations and reflections | c %--------------------------------------------% c call zlaset ('All', kplusp, kplusp, zero, one, q, ldq) c c %----------------------------------------------% c | Quick return if there are no shifts to apply | c %----------------------------------------------% c if (np .eq. 0) go to 9000 c c %----------------------------------------------% c | Chase the bulge with the application of each | c | implicit shift. Each shift is applied to the | c | whole matrix including each block. | c %----------------------------------------------% c do 110 jj = 1, np sigma = shift(jj) c if (msglvl .gt. 2 ) then call ivout (logfil, 1, jj, ndigit, & '_napps: shift number.') call zvout (logfil, 1, sigma, ndigit, & '_napps: Value of the shift ') end if c istart = 1 20 continue c do 30 i = istart, kplusp-1 c c %----------------------------------------% c | Check for splitting and deflation. Use | c | a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr | c %----------------------------------------% c tst1 = zabs1( h( i, i ) ) + zabs1( h( i+1, i+1 ) ) if( tst1.eq.rzero ) & tst1 = zlanhs( '1', kplusp-jj+1, h, ldh, workl ) if ( abs(dble(h(i+1,i))) & .le. max(ulp*tst1, smlnum) ) then if (msglvl .gt. 0) then call ivout (logfil, 1, i, ndigit, & '_napps: matrix splitting at row/column no.') call ivout (logfil, 1, jj, ndigit, & '_napps: matrix splitting with shift number.') call zvout (logfil, 1, h(i+1,i), ndigit, & '_napps: off diagonal element.') end if iend = i h(i+1,i) = zero go to 40 end if 30 continue iend = kplusp 40 continue c if (msglvl .gt. 2) then call ivout (logfil, 1, istart, ndigit, & '_napps: Start of current block ') call ivout (logfil, 1, iend, ndigit, & '_napps: End of current block ') end if c c %------------------------------------------------% c | No reason to apply a shift to block of order 1 | c | or if the current block starts after the point | c | of compression since we'll discard this stuff | c %------------------------------------------------% c if ( istart .eq. iend .or. istart .gt. kev) go to 100 c h11 = h(istart,istart) h21 = h(istart+1,istart) f = h11 - sigma g = h21 c do 80 i = istart, iend-1 c c %------------------------------------------------------% c | Construct the plane rotation G to zero out the bulge | c %------------------------------------------------------% c call zlartg (f, g, c, s, r) if (i .gt. istart) then h(i,i-1) = r h(i+1,i-1) = zero end if c c %---------------------------------------------% c | Apply rotation to the left of H; H <- G'*H | c %---------------------------------------------% c do 50 j = i, kplusp t = c*h(i,j) + s*h(i+1,j) h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j) h(i,j) = t 50 continue c c %---------------------------------------------% c | Apply rotation to the right of H; H <- H*G | c %---------------------------------------------% c do 60 j = 1, min(i+2,iend) t = c*h(j,i) + conjg(s)*h(j,i+1) h(j,i+1) = -s*h(j,i) + c*h(j,i+1) h(j,i) = t 60 continue c c %-----------------------------------------------------% c | Accumulate the rotation in the matrix Q; Q <- Q*G' | c %-----------------------------------------------------% c do 70 j = 1, min(i+jj, kplusp) t = c*q(j,i) + conjg(s)*q(j,i+1) q(j,i+1) = - s*q(j,i) + c*q(j,i+1) q(j,i) = t 70 continue c c %---------------------------% c | Prepare for next rotation | c %---------------------------% c if (i .lt. iend-1) then f = h(i+1,i) g = h(i+2,i) end if 80 continue c c %-------------------------------% c | Finished applying the shift. | c %-------------------------------% c 100 continue c c %---------------------------------------------------------% c | Apply the same shift to the next block if there is any. | c %---------------------------------------------------------% c istart = iend + 1 if (iend .lt. kplusp) go to 20 c c %---------------------------------------------% c | Loop back to the top to get the next shift. | c %---------------------------------------------% c 110 continue c c %---------------------------------------------------% c | Perform a similarity transformation that makes | c | sure that the compressed H will have non-negative | c | real subdiagonal elements. | c %---------------------------------------------------% c do 120 j=1,kev if ( dble( h(j+1,j) ) .lt. rzero .or. & dimag( h(j+1,j) ) .ne. rzero ) then t = h(j+1,j) / dlapy2(dble(h(j+1,j)),dimag(h(j+1,j))) call zscal( kplusp-j+1, conjg(t), h(j+1,j), ldh ) call zscal( min(j+2, kplusp), t, h(1,j+1), 1 ) call zscal( min(j+np+1,kplusp), t, q(1,j+1), 1 ) h(j+1,j) = dcmplx( dble( h(j+1,j) ), rzero ) end if 120 continue c do 130 i = 1, kev c c %--------------------------------------------% c | Final check for splitting and deflation. | c | Use a standard test as in the QR algorithm | c | REFERENCE: LAPACK subroutine zlahqr. | c | Note: Since the subdiagonals of the | c | compressed H are nonnegative real numbers, | c | we take advantage of this. | c %--------------------------------------------% c tst1 = zabs1( h( i, i ) ) + zabs1( h( i+1, i+1 ) ) if( tst1 .eq. rzero ) & tst1 = zlanhs( '1', kev, h, ldh, workl ) if( dble( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) ) & h(i+1,i) = zero 130 continue c c %-------------------------------------------------% c | Compute the (kev+1)-st column of (V*Q) and | c | temporarily store the result in WORKD(N+1:2*N). | c | This is needed in the residual update since we | c | cannot GUARANTEE that the corresponding entry | c | of H would be zero as in exact arithmetic. | c %-------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero, & workd(n+1), 1) c c %----------------------------------------------------------% c | Compute column 1 to kev of (V*Q) in backward order | c | taking advantage of the upper Hessenberg structure of Q. | c %----------------------------------------------------------% c do 140 i = 1, kev call zgemv ('N', n, kplusp-i+1, one, v, ldv, & q(1,kev-i+1), 1, zero, workd, 1) call zcopy (n, workd, 1, v(1,kplusp-i+1), 1) 140 continue c c %-------------------------------------------------% c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). | c %-------------------------------------------------% c call zlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv) c c %--------------------------------------------------------------% c | Copy the (kev+1)-st column of (V*Q) in the appropriate place | c %--------------------------------------------------------------% c if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zcopy (n, workd(n+1), 1, v(1,kev+1), 1) c c %-------------------------------------% c | Update the residual vector: | c | r <- sigmak*r + betak*v(:,kev+1) | c | where | c | sigmak = (e_{kev+p}'*Q)*e_{kev} | c | betak = e_{kev+1}'*H*e_{kev} | c %-------------------------------------% c call zscal (n, q(kplusp,kev), resid, 1) if ( dble( h(kev+1,kev) ) .gt. rzero ) & call zaxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1) c if (msglvl .gt. 1) then call zvout (logfil, 1, q(kplusp,kev), ndigit, & '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}') call zvout (logfil, 1, h(kev+1,kev), ndigit, & '_napps: betak = e_{kev+1}^T*H*e_{kev}') call ivout (logfil, 1, kev, ndigit, & '_napps: Order of the final Hessenberg matrix ') if (msglvl .gt. 2) then call zmout (logfil, kev, kev, h, ldh, ndigit, & '_napps: updated Hessenberg matrix H for next iteration') end if c end if c 9000 continue call arscnd (t1) tcapps = tcapps + (t1 - t0) c return c c %---------------% c | End of znapps | c %---------------% c end arpack-ng-3.3.0/SRC/znaup2.f000066400000000000000000000710471260666001200154050ustar00rootroot00000000000000c\BeginDoc c c\Name: znaup2 c c\Description: c Intermediate level interface called by znaupd . c c\Usage: c call znaup2 c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD, c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO ) c c\Arguments c c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in znaupd . c MODE, ISHIFT, MXITER: see the definition of IPARAM in znaupd . c c NP Integer. (INPUT/OUTPUT) c Contains the number of implicit shifts to apply during c each Arnoldi iteration. c If ISHIFT=1, NP is adjusted dynamically at each iteration c to accelerate convergence and prevent stagnation. c This is also roughly equal to the number of matrix-vector c products (involving the operator OP) per Arnoldi iteration. c The logic for adjusting is contained within the current c subroutine. c If ISHIFT=0, NP is the number of shifts the user needs c to provide via reverse comunication. 0 < NP < NCV-NEV. c NP may be less than NCV-NEV since a leading block of the current c upper Hessenberg matrix has split off and contains "unwanted" c Ritz values. c Upon termination of the IRA iteration, NP contains the number c of "converged" wanted Ritz values. c c IUPD Integer. (INPUT) c IUPD .EQ. 0: use explicit restart instead implicit update. c IUPD .NE. 0: use implicit update. c c V Complex*16 N by (NEV+NP) array. (INPUT/OUTPUT) c The Arnoldi basis vectors are returned in the first NEV c columns of V. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling c program. c c H Complex*16 (NEV+NP) by (NEV+NP) array. (OUTPUT) c H is used to store the generated upper Hessenberg matrix c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length NEV+NP. (OUTPUT) c RITZ(1:NEV) contains the computed Ritz values of OP. c c BOUNDS Complex*16 array of length NEV+NP. (OUTPUT) c BOUNDS(1:NEV) contain the error bounds corresponding to c the computed Ritz values. c c Q Complex*16 (NEV+NP) by (NEV+NP) array. (WORKSPACE) c Private (replicated) work array used to accumulate the c rotation in the shift application step. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length at least c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. It is used in shifts calculation, shifts c application and convergence checking. c c c IPNTR Integer array of length 3. (OUTPUT) c Pointer to mark the starting locations in the WORKD for c vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X. c IPNTR(2): pointer to the current result vector Y. c IPNTR(3): pointer to the vector B * X when used in the c shift-and-invert mode. X is the current operand. c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (WORKSPACE) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note in ZNAUPD . c c RWORK Double precision work array of length NEV+NP ( WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal return. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. c NP returns the number of converged Ritz values. c = 2: No shifts could be applied. c = -8: Error return from LAPACK eigenvalue calculation; c This should never happen. c = -9: Starting vector is zero. c = -9999: Could not build an Arnoldi factorization. c Size that was built in returned in NP. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c c\Routines called: c zgetv0 ARPACK initial vector generation routine. c znaitr ARPACK Arnoldi factorization routine. c znapps ARPACK application of implicit shifts routine. c zneigh ARPACK compute Ritz values and error bounds routine. c zngets ARPACK reorder Ritz values and error bounds routine. c zsortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c zmout ARPACK utility routine that prints matrices c zvout ARPACK utility routine that prints vectors. c dvout ARPACK utility routine that prints vectors. c dlamch LAPACK routine that determines machine constants. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c zcopy Level 1 BLAS that copies one vector to another . c zdotc Level 1 BLAS that computes the scalar product of two vectors. c zswap Level 1 BLAS that swaps two vectors. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice Universitya c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naup2.F SID: 2.6 DATE OF SID: 06/01/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c c----------------------------------------------------------------------- c subroutine znaup2 & ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, h, ldh, ritz, bounds, & q, ldq, workl, ipntr, workd, rwork, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter, & n, nev, np Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer ipntr(13) Complex*16 & bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), & resid(n), ritz(nev+np), v(ldv,nev+np), & workd(3*n), workl( (nev+np)*(nev+np+3) ) Double precision & rwork(nev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rzero parameter (one = (1.0D+0, 0.0D+0) , zero = (0.0D+0, 0.0D+0) , & rzero = 0.0D+0 ) c c %---------------% c | Local Scalars | c %---------------% c logical cnorm , getv0, initv , update, ushift integer ierr , iter , kplusp, msglvl, nconv, & nevbef, nev0 , np0 , nptemp, i , & j Complex*16 & cmpnorm Double precision & rnorm , eps23, rtemp character wprime*2 c save cnorm, getv0, initv , update, ushift, & rnorm, iter , kplusp, msglvl, nconv , & nevbef, nev0 , np0 , eps23 c c c %-----------------------% c | Local array arguments | c %-----------------------% c integer kp(3) c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy , zgetv0 , znaitr , zneigh , zngets , znapps , & zsortc , zswap , zmout , zvout , ivout, arscnd c c %--------------------% c | External functions | c %--------------------% c Complex*16 & zdotc Double precision & dznrm2 , dlamch , dlapy2 external zdotc , dznrm2 , dlamch , dlapy2 c c %---------------------% c | Intrinsic Functions | c %---------------------% c intrinsic dimag , dble , min, max c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c call arscnd (t0) c msglvl = mcaup2 c nev0 = nev np0 = np c c %-------------------------------------% c | kplusp is the bound on the largest | c | Lanczos factorization built. | c | nconv is the current number of | c | "converged" eigenvalues. | c | iter is the counter on the current | c | iteration step. | c %-------------------------------------% c kplusp = nev + np nconv = 0 iter = 0 c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = dlamch ('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0 ) c c %---------------------------------------% c | Set flags for computing the first NEV | c | steps of the Arnoldi factorization. | c %---------------------------------------% c getv0 = .true. update = .false. ushift = .false. cnorm = .false. c if (info .ne. 0) then c c %--------------------------------------------% c | User provides the initial residual vector. | c %--------------------------------------------% c initv = .true. info = 0 else initv = .false. end if end if c c %---------------------------------------------% c | Get a possibly random starting vector and | c | force it into the range of the operator OP. | c %---------------------------------------------% c 10 continue c if (getv0) then call zgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm, & ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (rnorm .eq. rzero) then c c %-----------------------------------------% c | The initial vector is zero. Error exit. | c %-----------------------------------------% c info = -9 go to 1100 end if getv0 = .false. ido = 0 end if c c %-----------------------------------% c | Back from reverse communication : | c | continue with update step | c %-----------------------------------% c if (update) go to 20 c c %-------------------------------------------% c | Back from computing user specified shifts | c %-------------------------------------------% c if (ushift) go to 50 c c %-------------------------------------% c | Back from computing residual norm | c | at the end of the current iteration | c %-------------------------------------% c if (cnorm) go to 100 c c %----------------------------------------------------------% c | Compute the first NEV steps of the Arnoldi factorization | c %----------------------------------------------------------% c call znaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv, & h, ldh, ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if c c %--------------------------------------------------------------% c | | c | M A I N ARNOLDI I T E R A T I O N L O O P | c | Each iteration implicitly restarts the Arnoldi | c | factorization in place. | c | | c %--------------------------------------------------------------% c 1000 continue c iter = iter + 1 c if (msglvl .gt. 0) then call ivout (logfil, 1, iter, ndigit, & '_naup2: **** Start of major iteration number ****') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c | Adjust NP since NEV might have been updated by last call | c | to the shift application routine znapps . | c %-----------------------------------------------------------% c np = kplusp - nev c if (msglvl .gt. 1) then call ivout (logfil, 1, nev, ndigit, & '_naup2: The length of the current Arnoldi factorization') call ivout (logfil, 1, np, ndigit, & '_naup2: Extend the Arnoldi factorization by') end if c c %-----------------------------------------------------------% c | Compute NP additional steps of the Arnoldi factorization. | c %-----------------------------------------------------------% c ido = 0 20 continue update = .true. c call znaitr (ido, bmat, n, nev, np, mode, resid, rnorm, & v , ldv , h, ldh, ipntr, workd, info) c if (ido .ne. 99) go to 9000 c if (info .gt. 0) then np = info mxiter = iter info = -9999 go to 1200 end if update = .false. c if (msglvl .gt. 1) then call dvout (logfil, 1, rnorm, ndigit, & '_naup2: Corresponding B-norm of the residual') end if c c %--------------------------------------------------------% c | Compute the eigenvalues and corresponding error bounds | c | of the current upper Hessenberg matrix. | c %--------------------------------------------------------% c call zneigh (rnorm, kplusp, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c if (ierr .ne. 0) then info = -8 go to 1200 end if c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | error bounds are in the last NEV loc. of RITZ, | c | and BOUNDS respectively. | c %---------------------------------------------------% c nev = nev0 np = np0 c c %--------------------------------------------------% c | Make a copy of Ritz values and the corresponding | c | Ritz estimates obtained from zneigh . | c %--------------------------------------------------% c call zcopy (kplusp,ritz,1,workl(kplusp**2+1),1) call zcopy (kplusp,bounds,1,workl(kplusp**2+kplusp+1),1) c c %---------------------------------------------------% c | Select the wanted Ritz values and their bounds | c | to be used in the convergence test. | c | The wanted part of the spectrum and corresponding | c | bounds are in the last NEV loc. of RITZ | c | BOUNDS respectively. | c %---------------------------------------------------% c call zngets (ishift, which, nev, np, ritz, bounds) c c %------------------------------------------------------------% c | Convergence test: currently we use the following criteria. | c | The relative accuracy of a Ritz value is considered | c | acceptable if: | c | | c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). | c | | c %------------------------------------------------------------% c nconv = 0 c do 25 i = 1, nev rtemp = max( eps23, dlapy2 ( dble (ritz(np+i)), & dimag (ritz(np+i)) ) ) if ( dlapy2 (dble (bounds(np+i)),dimag (bounds(np+i))) & .le. tol*rtemp ) then nconv = nconv + 1 end if 25 continue c if (msglvl .gt. 2) then kp(1) = nev kp(2) = np kp(3) = nconv call ivout (logfil, 3, kp, ndigit, & '_naup2: NEV, NP, NCONV are') call zvout (logfil, kplusp, ritz, ndigit, & '_naup2: The eigenvalues of H') call zvout (logfil, kplusp, bounds, ndigit, & '_naup2: Ritz estimates of the current NCV Ritz values') end if c c %---------------------------------------------------------% c | Count the number of unwanted Ritz values that have zero | c | Ritz estimates. If any Ritz estimates are equal to zero | c | then a leading block of H of order equal to at least | c | the number of Ritz values with zero Ritz estimates has | c | split off. None of these Ritz values may be removed by | c | shifting. Decrease NP the number of shifts to apply. If | c | no shifts may be applied, then prepare to exit | c %---------------------------------------------------------% c nptemp = np do 30 j=1, nptemp if (bounds(j) .eq. zero) then np = np - 1 nev = nev + 1 end if 30 continue c if ( (nconv .ge. nev0) .or. & (iter .gt. mxiter) .or. & (np .eq. 0) ) then c if (msglvl .gt. 4) then call zvout (logfil, kplusp, workl(kplusp**2+1), ndigit, & '_naup2: Eigenvalues computed by _neigh:') call zvout (logfil, kplusp, workl(kplusp**2+kplusp+1), & ndigit, & '_naup2: Ritz estimates computed by _neigh:') end if c c %------------------------------------------------% c | Prepare to exit. Put the converged Ritz values | c | and corresponding bounds in RITZ(1:NCONV) and | c | BOUNDS(1:NCONV) respectively. Then sort. Be | c | careful when NCONV > NP | c %------------------------------------------------% c c %------------------------------------------% c | Use h( 3,1 ) as storage to communicate | c | rnorm to zneupd if needed | c %------------------------------------------% h(3,1) = dcmplx (rnorm,rzero) c c %----------------------------------------------% c | Sort Ritz values so that converged Ritz | c | values appear within the first NEV locations | c | of ritz and bounds, and the most desired one | c | appears at the front. | c %----------------------------------------------% c if (which .eq. 'LM') wprime = 'SM' if (which .eq. 'SM') wprime = 'LM' if (which .eq. 'LR') wprime = 'SR' if (which .eq. 'SR') wprime = 'LR' if (which .eq. 'LI') wprime = 'SI' if (which .eq. 'SI') wprime = 'LI' c call zsortc (wprime, .true., kplusp, ritz, bounds) c c %--------------------------------------------------% c | Scale the Ritz estimate of each Ritz value | c | by 1 / max(eps23, magnitude of the Ritz value). | c %--------------------------------------------------% c do 35 j = 1, nev0 rtemp = max( eps23, dlapy2 ( dble (ritz(j)), & dimag (ritz(j)) ) ) bounds(j) = bounds(j)/rtemp 35 continue c c %---------------------------------------------------% c | Sort the Ritz values according to the scaled Ritz | c | estimates. This will push all the converged ones | c | towards the front of ritz, bounds (in the case | c | when NCONV < NEV.) | c %---------------------------------------------------% c wprime = 'LM' call zsortc (wprime, .true., nev0, bounds, ritz) c c %----------------------------------------------% c | Scale the Ritz estimate back to its original | c | value. | c %----------------------------------------------% c do 40 j = 1, nev0 rtemp = max( eps23, dlapy2 ( dble (ritz(j)), & dimag (ritz(j)) ) ) bounds(j) = bounds(j)*rtemp 40 continue c c %-----------------------------------------------% c | Sort the converged Ritz values again so that | c | the "threshold" value appears at the front of | c | ritz and bound. | c %-----------------------------------------------% c call zsortc (which, .true., nconv, ritz, bounds) c if (msglvl .gt. 1) then call zvout (logfil, kplusp, ritz, ndigit, & '_naup2: Sorted eigenvalues') call zvout (logfil, kplusp, bounds, ndigit, & '_naup2: Sorted ritz estimates.') end if c c %------------------------------------% c | Max iterations have been exceeded. | c %------------------------------------% c if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1 c c %---------------------% c | No shifts to apply. | c %---------------------% c if (np .eq. 0 .and. nconv .lt. nev0) info = 2 c np = nconv go to 1100 c else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then c c %-------------------------------------------------% c | Do not have all the requested eigenvalues yet. | c | To prevent possible stagnation, adjust the size | c | of NEV. | c %-------------------------------------------------% c nevbef = nev nev = nev + min(nconv, np/2) if (nev .eq. 1 .and. kplusp .ge. 6) then nev = kplusp / 2 else if (nev .eq. 1 .and. kplusp .gt. 3) then nev = 2 end if np = kplusp - nev c c %---------------------------------------% c | If the size of NEV was just increased | c | resort the eigenvalues. | c %---------------------------------------% c if (nevbef .lt. nev) & call zngets (ishift, which, nev, np, ritz, bounds) c end if c if (msglvl .gt. 0) then call ivout (logfil, 1, nconv, ndigit, & '_naup2: no. of "converged" Ritz values at this iter.') if (msglvl .gt. 1) then kp(1) = nev kp(2) = np call ivout (logfil, 2, kp, ndigit, & '_naup2: NEV and NP are') call zvout (logfil, nev, ritz(np+1), ndigit, & '_naup2: "wanted" Ritz values ') call zvout (logfil, nev, bounds(np+1), ndigit, & '_naup2: Ritz estimates of the "wanted" values ') end if end if c if (ishift .eq. 0) then c c %-------------------------------------------------------% c | User specified shifts: pop back out to get the shifts | c | and return them in the first 2*NP locations of WORKL. | c %-------------------------------------------------------% c ushift = .true. ido = 3 go to 9000 end if 50 continue ushift = .false. c if ( ishift .ne. 1 ) then c c %----------------------------------% c | Move the NP shifts from WORKL to | c | RITZ, to free up WORKL | c | for non-exact shift case. | c %----------------------------------% c call zcopy (np, workl, 1, ritz, 1) end if c if (msglvl .gt. 2) then call ivout (logfil, 1, np, ndigit, & '_naup2: The number of shifts to apply ') call zvout (logfil, np, ritz, ndigit, & '_naup2: values of the shifts') if ( ishift .eq. 1 ) & call zvout (logfil, np, bounds, ndigit, & '_naup2: Ritz estimates of the shifts') end if c c %---------------------------------------------------------% c | Apply the NP implicit shifts by QR bulge chasing. | c | Each shift is applied to the whole upper Hessenberg | c | matrix H. | c | The first 2*N locations of WORKD are used as workspace. | c %---------------------------------------------------------% c call znapps (n, nev, np, ritz, v, ldv, & h, ldh, resid, q, ldq, workl, workd) c c %---------------------------------------------% c | Compute the B-norm of the updated residual. | c | Keep B*RESID in WORKD(1:N) to be used in | c | the first step of the next call to znaitr . | c %---------------------------------------------% c cnorm = .true. call arscnd (t2) if (bmat .eq. 'G') then nbx = nbx + 1 call zcopy (n, resid, 1, workd(n+1), 1) ipntr(1) = n + 1 ipntr(2) = 1 ido = 2 c c %----------------------------------% c | Exit in order to compute B*RESID | c %----------------------------------% c go to 9000 else if (bmat .eq. 'I') then call zcopy (n, resid, 1, workd, 1) end if c 100 continue c c %----------------------------------% c | Back from reverse communication; | c | WORKD(1:N) := B*RESID | c %----------------------------------% c if (bmat .eq. 'G') then call arscnd (t3) tmvbx = tmvbx + (t3 - t2) end if c if (bmat .eq. 'G') then cmpnorm = zdotc (n, resid, 1, workd, 1) rnorm = sqrt(dlapy2 (dble (cmpnorm),dimag (cmpnorm))) else if (bmat .eq. 'I') then rnorm = dznrm2 (n, resid, 1) end if cnorm = .false. c if (msglvl .gt. 2) then call dvout (logfil, 1, rnorm, ndigit, & '_naup2: B-norm of residual for compressed factorization') call zmout (logfil, nev, nev, h, ldh, ndigit, & '_naup2: Compressed upper Hessenberg matrix H') end if c go to 1000 c c %---------------------------------------------------------------% c | | c | E N D O F M A I N I T E R A T I O N L O O P | c | | c %---------------------------------------------------------------% c 1100 continue c mxiter = iter nev = nconv c 1200 continue ido = 99 c c %------------% c | Error Exit | c %------------% c call arscnd (t1) tcaup2 = t1 - t0 c 9000 continue c c %---------------% c | End of znaup2 | c %---------------% c return end arpack-ng-3.3.0/SRC/znaupd.f000066400000000000000000000661721260666001200154720ustar00rootroot00000000000000c\BeginDoc c c\Name: znaupd c c\Description: c Reverse communication interface for the Implicitly Restarted Arnoldi c iteration. This is intended to be used to find a few eigenpairs of a c complex linear operator OP with respect to a semi-inner product defined c by a hermitian positive semi-definite real matrix B. B may be the identity c matrix. NOTE: if both OP and B are real, then dsaupd or dnaupd should c be used. c c c The computed approximate eigenvalues are called Ritz values and c the corresponding approximate eigenvectors are called Ritz vectors. c c znaupd is usually called iteratively to solve one of the c following problems: c c Mode 1: A*x = lambda*x. c ===> OP = A and B = I. c c Mode 2: A*x = lambda*M*x, M hermitian positive definite c ===> OP = inv[M]*A and B = M. c ===> (If M can be factored see remark 3 below) c c Mode 3: A*x = lambda*M*x, M hermitian semi-definite c ===> OP = inv[A - sigma*M]*M and B = M. c ===> shift-and-invert mode c If OP*x = amu*x, then lambda = sigma + 1/amu. c c c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v c should be accomplished either by a direct method c using a sparse matrix factorization and solving c c [A - sigma*M]*w = v or M*w = v, c c or through an iterative method for solving these c systems. If an iterative method is used, the c convergence test must be more stringent than c the accuracy requirements for the eigenvalue c approximations. c c\Usage: c call znaupd c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO ) c c\Arguments c IDO Integer. (INPUT/OUTPUT) c Reverse communication flag. IDO must be zero on the first c call to znaupd . IDO will be set internally to c indicate the type of operation to be performed. Control is c then given back to the calling routine which has the c responsibility to carry out the requested operation and call c znaupd with the result. The operand is given in c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)). c ------------------------------------------------------------- c IDO = 0: first call to the reverse communication interface c IDO = -1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c This is for the initialization phase to force the c starting vector into the range of OP. c IDO = 1: compute Y = OP * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c In mode 3, the vector B * X is already c available in WORKD(ipntr(3)). It does not c need to be recomputed in forming OP * X. c IDO = 2: compute Y = M * X where c IPNTR(1) is the pointer into WORKD for X, c IPNTR(2) is the pointer into WORKD for Y. c IDO = 3: compute and return the shifts in the first c NP locations of WORKL. c IDO = 99: done c ------------------------------------------------------------- c After the initialization phase, when the routine is used in c the "shift-and-invert" mode, the vector M * X is already c available and does not need to be recomputed in forming OP*X. c c BMAT Character*1. (INPUT) c BMAT specifies the type of the matrix B that defines the c semi-inner product for the operator OP. c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x c c N Integer. (INPUT) c Dimension of the eigenproblem. c c WHICH Character*2. (INPUT) c 'LM' -> want the NEV eigenvalues of largest magnitude. c 'SM' -> want the NEV eigenvalues of smallest magnitude. c 'LR' -> want the NEV eigenvalues of largest real part. c 'SR' -> want the NEV eigenvalues of smallest real part. c 'LI' -> want the NEV eigenvalues of largest imaginary part. c 'SI' -> want the NEV eigenvalues of smallest imaginary part. c c NEV Integer. (INPUT) c Number of eigenvalues of OP to be computed. 0 < NEV < N-1. c c TOL Double precision scalar. (INPUT) c Stopping criteria: the relative accuracy of the Ritz value c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)) c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex. c DEFAULT = dlamch ('EPS') (machine precision as computed c by the LAPACK auxiliary subroutine dlamch ). c c RESID Complex*16 array of length N. (INPUT/OUTPUT) c On INPUT: c If INFO .EQ. 0, a random initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c On OUTPUT: c RESID contains the final residual vector. c c NCV Integer. (INPUT) c Number of columns of the matrix V. NCV must satisfy the two c inequalities 1 <= NCV-NEV and NCV <= N. c This will indicate how many Arnoldi vectors are generated c at each iteration. After the startup phase in which NEV c Arnoldi vectors are generated, the algorithm generates c approximately NCV-NEV Arnoldi vectors at each subsequent update c iteration. Most of the cost in generating each Arnoldi vector is c in the matrix-vector operation OP*x. (See remark 4 below.) c c V Complex*16 array N by NCV. (OUTPUT) c Contains the final set of Arnoldi basis vectors. c c LDV Integer. (INPUT) c Leading dimension of V exactly as declared in the calling program. c c IPARAM Integer array of length 11. (INPUT/OUTPUT) c IPARAM(1) = ISHIFT: method for selecting the implicit shifts. c The shifts selected at each iteration are used to filter out c the components of the unwanted eigenvector. c ------------------------------------------------------------- c ISHIFT = 0: the shifts are to be provided by the user via c reverse communication. The NCV eigenvalues of c the Hessenberg matrix H are returned in the part c of WORKL array corresponding to RITZ. c ISHIFT = 1: exact shifts with respect to the current c Hessenberg matrix H. This is equivalent to c restarting the iteration from the beginning c after updating the starting vector with a linear c combination of Ritz vectors associated with the c "wanted" eigenvalues. c ISHIFT = 2: other choice of internal shift to be defined. c ------------------------------------------------------------- c c IPARAM(2) = No longer referenced c c IPARAM(3) = MXITER c On INPUT: maximum number of Arnoldi update iterations allowed. c On OUTPUT: actual number of Arnoldi update iterations taken. c c IPARAM(4) = NB: blocksize to be used in the recurrence. c The code currently works only for NB = 1. c c IPARAM(5) = NCONV: number of "converged" Ritz values. c This represents the number of Ritz values that satisfy c the convergence criterion. c c IPARAM(6) = IUPD c No longer referenced. Implicit restarting is ALWAYS used. c c IPARAM(7) = MODE c On INPUT determines what type of eigenproblem is being solved. c Must be 1,2,3; See under \Description of znaupd for the c four modes available. c c IPARAM(8) = NP c When ido = 3 and the user provides shifts through reverse c communication (IPARAM(1)=0), _naupd returns NP, the number c of shifts the user is to provide. 0 < NP < NCV-NEV. c c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO, c OUTPUT: NUMOP = total number of OP*x operations, c NUMOPB = total number of B*x operations if BMAT='G', c NUMREO = total number of steps of re-orthogonalization. c c IPNTR Integer array of length 14. (OUTPUT) c Pointer to mark the starting locations in the WORKD and WORKL c arrays for matrices/vectors used by the Arnoldi iteration. c ------------------------------------------------------------- c IPNTR(1): pointer to the current operand vector X in WORKD. c IPNTR(2): pointer to the current result vector Y in WORKD. c IPNTR(3): pointer to the vector B * X in WORKD when used in c the shift-and-invert mode. c IPNTR(4): pointer to the next available location in WORKL c that is untouched by the program. c IPNTR(5): pointer to the NCV by NCV upper Hessenberg c matrix H in WORKL. c IPNTR(6): pointer to the ritz value array RITZ c IPNTR(7): pointer to the (projected) ritz vector array Q c IPNTR(8): pointer to the error BOUNDS array in WORKL. c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below. c c Note: IPNTR(9:13) is only referenced by zneupd . See Remark 2 below. c c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not Used c IPNTR(11): pointer to the NCV corresponding error bounds. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c zneupd if RVEC = .TRUE. See Remark 2 below. c c ------------------------------------------------------------- c c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION) c Distributed array to be used in the basic Arnoldi iteration c for reverse communication. The user should not use WORKD c as temporary workspace during the iteration !!!!!!!!!! c See Data Distribution Note below. c c WORKL Complex*16 work array of length LWORKL. (OUTPUT/WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. See Data Distribution Note below. c c LWORKL Integer. (INPUT) c LWORKL must be at least 3*NCV**2 + 5*NCV. c c RWORK Double precision work array of length NCV (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c c INFO Integer. (INPUT/OUTPUT) c If INFO .EQ. 0, a randomly initial residual vector is used. c If INFO .NE. 0, RESID contains the initial residual vector, c possibly from a previous run. c Error flag on output. c = 0: Normal exit. c = 1: Maximum number of iterations taken. c All possible eigenvalues of OP has been found. IPARAM(5) c returns the number of wanted converged Ritz values. c = 2: No longer an informational error. Deprecated starting c with release 2 of ARPACK. c = 3: No shifts could be applied during a cycle of the c Implicitly restarted Arnoldi iteration. One possibility c is to increase the size of NCV relative to NEV. c See remark 4 below. c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 2 and less than or equal to N. c = -4: The maximum number of Arnoldi update iteration c must be greater than zero. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation; c = -9: Starting vector is zero. c = -10: IPARAM(7) must be 1,2,3. c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: IPARAM(1) must be equal to 0 or 1. c = -9999: Could not build an Arnoldi factorization. c User input error highly likely. Please c check actual array dimensions and layout. c IPARAM(5) returns the size of the current Arnoldi c factorization. c c\Remarks c 1. The computed Ritz values are approximate eigenvalues of OP. The c selection of WHICH should be made with this in mind when using c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will c compute the NEV eigenvalues of the original problem that are c closest to the shift SIGMA . After convergence, approximate eigenvalues c of the original problem may be obtained with the ARPACK subroutine zneupd . c c 2. If a basis for the invariant subspace corresponding to the converged Ritz c values is needed, the user must call zneupd immediately following c completion of znaupd . This is new starting with release 2 of ARPACK. c c 3. If M can be factored into a Cholesky factorization M = LL` c then Mode = 2 should not be selected. Instead one should use c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular c linear systems should be solved with L and L` rather c than computing inverses. After convergence, an approximate c eigenvector z of the original problem is recovered by solving c L`z = x where x is a Ritz vector of OP. c c 4. At present there is no a-priori analysis to guide the selection c of NCV relative to NEV. The only formal requirement is that NCV > NEV + 1. c However, it is recommended that NCV .ge. 2*NEV. If many problems of c the same type are to be solved, one should experiment with increasing c NCV while keeping NEV fixed for a given test problem. This will c usually decrease the required number of OP*x operations but it c also increases the work and storage required to maintain the orthogonal c basis vectors. The optimal "cross-over" with respect to CPU time c is problem dependent and must be determined empirically. c See Chapter 8 of Reference 2 for further information. c c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the c NP = IPARAM(8) complex shifts in locations c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP). c Eigenvalues of the current upper Hessenberg matrix are located in c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered c according to the order defined by WHICH. The associated Ritz estimates c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , c WORKL(IPNTR(8)+NCV-1). c c----------------------------------------------------------------------- c c\Data Distribution Note: c c Fortran-D syntax: c ================ c Complex*16 resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) c decompose d1(n), d2(n,ncv) c align resid(i) with d1(i) c align v(i,j) with d2(i,j) c align workd(i) with d1(i) range (1:n) c align workd(i) with d1(i-n) range (n+1:2*n) c align workd(i) with d1(i-2*n) range (2*n+1:3*n) c distribute d1(block), d2(block,:) c replicated workl(lworkl) c c Cray MPP syntax: c =============== c Complex*16 resid(n), v(ldv,ncv), workd(n,3), workl(lworkl) c shared resid(block), v(block,:), workd(block,:) c replicated workl(lworkl) c c CM2/CM5 syntax: c ============== c c----------------------------------------------------------------------- c c include 'ex-nonsym.doc' c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for c _Real_ Matrices", Linear Algebra and its Applications, vol 88/89, c pp 575-595, (1987). c c\Routines called: c znaup2 ARPACK routine that implements the Implicitly Restarted c Arnoldi Iteration. c zstatn ARPACK routine that initializes the timing variables. c ivout ARPACK utility routine that prints integers. c zvout ARPACK utility routine that prints vectors. c arscnd ARPACK utility routine for timing. c dlamch LAPACK routine that determines machine constants. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: naupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2 c c\Remarks c c\EndLib c c----------------------------------------------------------------------- c subroutine znaupd & ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, & ipntr, workd, workl, lworkl, rwork, info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat*1, which*2 integer ido, info, ldv, lworkl, n, ncv, nev Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) Complex*16 & resid(n), v(ldv,ncv), workd(3*n), workl(lworkl) Double precision & rwork(ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0D+0, 0.0D+0) , zero = (0.0D+0, 0.0D+0) ) c c %---------------% c | Local Scalars | c %---------------% c integer bounds, ierr, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz, j save bounds, ih, iq, ishift, iupd, iw, & ldh, ldq, levec, mode, msglvl, mxiter, nb, & nev0, next, np, ritz c c %----------------------% c | External Subroutines | c %----------------------% c external znaup2 , zvout , ivout, arscnd, zstatn c c %--------------------% c | External Functions | c %--------------------% c Double precision & dlamch external dlamch c c %-----------------------% c | Executable Statements | c %-----------------------% c if (ido .eq. 0) then c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call zstatn call arscnd (t0) msglvl = mcaupd c c %----------------% c | Error checking | c %----------------% c ierr = 0 ishift = iparam(1) c levec = iparam(2) mxiter = iparam(3) c nb = iparam(4) nb = 1 c c %--------------------------------------------% c | Revision 2 performs only implicit restart. | c %--------------------------------------------% c iupd = 1 mode = iparam(7) c if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev .or. ncv .gt. n) then ierr = -3 else if (mxiter .le. 0) then ierr = -4 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 5*ncv) then ierr = -7 else if (mode .lt. 1 .or. mode .gt. 3) then ierr = -10 else if (mode .eq. 1 .and. bmat .eq. 'G') then ierr = -11 end if c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr ido = 99 go to 9000 end if c c %------------------------% c | Set default parameters | c %------------------------% c if (nb .le. 0) nb = 1 if (tol .le. 0.0D+0 ) tol = dlamch ('EpsMach') if (ishift .ne. 0 .and. & ishift .ne. 1 .and. & ishift .ne. 2) ishift = 1 c c %----------------------------------------------% c | NP is the number of additional steps to | c | extend the length NEV Lanczos factorization. | c | NEV0 is the local variable designating the | c | size of the invariant subspace desired. | c %----------------------------------------------% c np = ncv - nev nev0 = nev c c %-----------------------------% c | Zero out internal workspace | c %-----------------------------% c do 10 j = 1, 3*ncv**2 + 5*ncv workl(j) = zero 10 continue c c %-------------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q | c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace | c | The final workspace is needed by subroutine zneigh called | c | by znaup2 . Subroutine zneigh calls LAPACK routines for | c | calculating eigenvalues and the last row of the eigenvector | c | matrix. | c %-------------------------------------------------------------% c ldh = ncv ldq = ncv ih = 1 ritz = ih + ldh*ncv bounds = ritz + ncv iq = bounds + ncv iw = iq + ldq*ncv next = iw + ncv**2 + 3*ncv c ipntr(4) = next ipntr(5) = ih ipntr(6) = ritz ipntr(7) = iq ipntr(8) = bounds ipntr(14) = iw end if c c %-------------------------------------------------------% c | Carry out the Implicitly restarted Arnoldi Iteration. | c %-------------------------------------------------------% c call znaup2 & ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd, & ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz), & workl(bounds), workl(iq), ldq, workl(iw), & ipntr, workd, rwork, info ) c c %--------------------------------------------------% c | ido .ne. 99 implies use of reverse communication | c | to compute operations involving OP. | c %--------------------------------------------------% c if (ido .eq. 3) iparam(8) = np if (ido .ne. 99) go to 9000 c iparam(3) = mxiter iparam(5) = np iparam(9) = nopx iparam(10) = nbx iparam(11) = nrorth c c %------------------------------------% c | Exit if there was an informational | c | error within znaup2 . | c %------------------------------------% c if (info .lt. 0) go to 9000 if (info .eq. 2) info = 3 c if (msglvl .gt. 0) then call ivout (logfil, 1, mxiter, ndigit, & '_naupd: Number of update iterations taken') call ivout (logfil, 1, np, ndigit, & '_naupd: Number of wanted "converged" Ritz values') call zvout (logfil, np, workl(ritz), ndigit, & '_naupd: The final Ritz values') call zvout (logfil, np, workl(bounds), ndigit, & '_naupd: Associated Ritz estimates') end if c call arscnd (t1) tcaupd = t1 - t0 c if (msglvl .gt. 0) then c c %--------------------------------------------------------% c | Version Number & Version Date are defined in version.h | c %--------------------------------------------------------% c write (6,1000) write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt, & tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref, & tgetv0, tceigh, tcgets, tcapps, tcconv, trvec 1000 format (//, & 5x, '=============================================',/ & 5x, '= Complex implicit Arnoldi update code =',/ & 5x, '= Version Number: ', ' 2.3' , 21x, ' =',/ & 5x, '= Version Date: ', ' 07/31/96' , 16x, ' =',/ & 5x, '=============================================',/ & 5x, '= Summary of timing statistics =',/ & 5x, '=============================================',//) 1100 format ( & 5x, 'Total number update iterations = ', i5,/ & 5x, 'Total number of OP*x operations = ', i5,/ & 5x, 'Total number of B*x operations = ', i5,/ & 5x, 'Total number of reorthogonalization steps = ', i5,/ & 5x, 'Total number of iterative refinement steps = ', i5,/ & 5x, 'Total number of restart steps = ', i5,/ & 5x, 'Total time in user OP*x operation = ', f12.6,/ & 5x, 'Total time in user B*x operation = ', f12.6,/ & 5x, 'Total time in Arnoldi update routine = ', f12.6,/ & 5x, 'Total time in naup2 routine = ', f12.6,/ & 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/ & 5x, 'Total time in reorthogonalization phase = ', f12.6,/ & 5x, 'Total time in (re)start vector generation = ', f12.6,/ & 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/ & 5x, 'Total time in getting the shifts = ', f12.6,/ & 5x, 'Total time in applying the shifts = ', f12.6,/ & 5x, 'Total time in convergence testing = ', f12.6,/ & 5x, 'Total time in computing final Ritz vectors = ', f12.6/) end if c 9000 continue c return c c %---------------% c | End of znaupd | c %---------------% c end arpack-ng-3.3.0/SRC/zneigh.f000066400000000000000000000200701260666001200154400ustar00rootroot00000000000000c\BeginDoc c c\Name: zneigh c c\Description: c Compute the eigenvalues of the current upper Hessenberg matrix c and the corresponding Ritz estimates given the current residual norm. c c\Usage: c call zneigh c ( RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR ) c c\Arguments c RNORM Double precision scalar. (INPUT) c Residual norm corresponding to the current upper Hessenberg c matrix H. c c N Integer. (INPUT) c Size of the matrix H. c c H Complex*16 N by N array. (INPUT) c H contains the current upper Hessenberg matrix. c c LDH Integer. (INPUT) c Leading dimension of H exactly as declared in the calling c program. c c RITZ Complex*16 array of length N. (OUTPUT) c On output, RITZ(1:N) contains the eigenvalues of H. c c BOUNDS Complex*16 array of length N. (OUTPUT) c On output, BOUNDS contains the Ritz estimates associated with c the eigenvalues held in RITZ. This is equal to RNORM c times the last components of the eigenvectors corresponding c to the eigenvalues in RITZ. c c Q Complex*16 N by N array. (WORKSPACE) c Workspace needed to store the eigenvectors of H. c c LDQ Integer. (INPUT) c Leading dimension of Q exactly as declared in the calling c program. c c WORKL Complex*16 work array of length N**2 + 3*N. (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. This is needed to keep the full Schur form c of H and also in the calculation of the eigenvectors of H. c c RWORK Double precision work array of length N (WORKSPACE) c Private (replicated) array on each PE or array allocated on c the front end. c c IERR Integer. (OUTPUT) c Error exit flag from zlahqr or ztrevc. c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c zmout ARPACK utility routine that prints matrices c zvout ARPACK utility routine that prints vectors. c dvout ARPACK utility routine that prints vectors. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine to compute the Schur form of an c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form c zcopy Level 1 BLAS that copies one vector to another. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a vector. c c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neigh.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c None c c\EndLib c c----------------------------------------------------------------------- c subroutine zneigh (rnorm, n, h, ldh, ritz, bounds, & q, ldq, workl, rwork, ierr) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c integer ierr, n, ldh, ldq Double precision & rnorm c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(n), h(ldh,n), q(ldq,n), ritz(n), & workl(n*(n+3)) Double precision & rwork(n) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero Double precision & rone parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0), & rone = 1.0D+0) c c %------------------------% c | Local Scalars & Arrays | c %------------------------% c logical select(1) integer j, msglvl Complex*16 & vl(1) Double precision & temp c c %----------------------% c | External Subroutines | c %----------------------% c external zlacpy, zlahqr, ztrevc, zcopy, & zdscal, zmout, zvout, arscnd c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2 external dznrm2 c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mceigh c if (msglvl .gt. 2) then call zmout (logfil, n, n, h, ldh, ndigit, & '_neigh: Entering upper Hessenberg matrix H ') end if c c %----------------------------------------------------------% c | 1. Compute the eigenvalues, the last components of the | c | corresponding Schur vectors and the full Schur form T | c | of the current upper Hessenberg matrix H. | c | zlahqr returns the full Schur form of H | c | in WORKL(1:N**2), and the Schur vectors in q. | c %----------------------------------------------------------% c call zlacpy ('All', n, n, h, ldh, workl, n) call zlaset ('All', n, n, zero, one, q, ldq) call zlahqr (.true., .true., n, 1, n, workl, ldh, ritz, & 1, n, q, ldq, ierr) if (ierr .ne. 0) go to 9000 c call zcopy (n, q(n-1,1), ldq, bounds, 1) if (msglvl .gt. 1) then call zvout (logfil, n, bounds, ndigit, & '_neigh: last row of the Schur matrix for H') end if c c %----------------------------------------------------------% c | 2. Compute the eigenvectors of the full Schur form T and | c | apply the Schur vectors to get the corresponding | c | eigenvectors. | c %----------------------------------------------------------% c call ztrevc ('Right', 'Back', select, n, workl, n, vl, n, q, & ldq, n, n, workl(n*n+1), rwork, ierr) c if (ierr .ne. 0) go to 9000 c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1; here the magnitude of a complex | c | number (x,y) is taken to be |x| + |y|. | c %------------------------------------------------% c do 10 j=1, n temp = dznrm2( n, q(1,j), 1 ) call zdscal ( n, rone / temp, q(1,j), 1 ) 10 continue c if (msglvl .gt. 1) then call zcopy(n, q(n,1), ldq, workl, 1) call zvout (logfil, n, workl, ndigit, & '_neigh: Last row of the eigenvector matrix for H') end if c c %----------------------------% c | Compute the Ritz estimates | c %----------------------------% c call zcopy(n, q(n,1), n, bounds, 1) call zdscal(n, rnorm, bounds, 1) c if (msglvl .gt. 2) then call zvout (logfil, n, ritz, ndigit, & '_neigh: The eigenvalues of H') call zvout (logfil, n, bounds, ndigit, & '_neigh: Ritz estimates for the eigenvalues of H') end if c call arscnd(t1) tceigh = tceigh + (t1 - t0) c 9000 continue return c c %---------------% c | End of zneigh | c %---------------% c end arpack-ng-3.3.0/SRC/zneupd.f000066400000000000000000001042601260666001200154650ustar00rootroot00000000000000c\BeginDoc c c\Name: zneupd c c\Description: c This subroutine returns the converged approximations to eigenvalues c of A*z = lambda*B*z and (optionally): c c (1) The corresponding approximate eigenvectors; c c (2) An orthonormal basis for the associated approximate c invariant subspace; c c (3) Both. c c There is negligible additional cost to obtain eigenvectors. An orthonormal c basis is always computed. There is an additional storage cost of n*nev c if both are requested (in this case a separate array Z must be supplied). c c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z c are derived from approximate eigenvalues and eigenvectors of c of the linear operator OP prescribed by the MODE selection in the c call to ZNAUPD. ZNAUPD must be called before this routine is called. c These approximate eigenvalues and vectors are commonly called Ritz c values and Ritz vectors respectively. They are referred to as such c in the comments that follow. The computed orthonormal basis for the c invariant subspace corresponding to these Ritz values is referred to as a c Schur basis. c c The definition of OP as well as other terms and the relation of computed c Ritz values and vectors of OP with respect to the given problem c A*z = lambda*B*z may be found in the header of ZNAUPD. For a brief c description, see definitions of IPARAM(7), MODE and WHICH in the c documentation of ZNAUPD. c c\Usage: c call zneupd c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT, c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, c WORKL, LWORKL, RWORK, INFO ) c c\Arguments: c RVEC LOGICAL (INPUT) c Specifies whether a basis for the invariant subspace corresponding c to the converged Ritz value approximations for the eigenproblem c A*z = lambda*B*z is computed. c c RVEC = .FALSE. Compute Ritz values only. c c RVEC = .TRUE. Compute Ritz vectors or Schur vectors. c See Remarks below. c c HOWMNY Character*1 (INPUT) c Specifies the form of the basis for the invariant subspace c corresponding to the converged Ritz values that is to be computed. c c = 'A': Compute NEV Ritz vectors; c = 'P': Compute NEV Schur vectors; c = 'S': compute some of the Ritz vectors, specified c by the logical array SELECT. c c SELECT Logical array of dimension NCV. (INPUT) c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be c computed. To select the Ritz vector corresponding to a c Ritz value D(j), SELECT(j) must be set to .TRUE.. c If HOWMNY = 'A' or 'P', SELECT need not be initialized c but it is used as internal workspace. c c D Complex*16 array of dimension NEV+1. (OUTPUT) c On exit, D contains the Ritz approximations c to the eigenvalues lambda for A*z = lambda*B*z. c c Z Complex*16 N by NEV array (OUTPUT) c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of c Z represents approximate eigenvectors (Ritz vectors) corresponding c to the NCONV=IPARAM(5) Ritz values for eigensystem c A*z = lambda*B*z. c c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED. c c NOTE: If if RVEC = .TRUE. and a Schur basis is not required, c the array Z may be set equal to first NEV+1 columns of the Arnoldi c basis array V computed by ZNAUPD. In this case the Arnoldi basis c will be destroyed and overwritten with the eigenvector basis. c c LDZ Integer. (INPUT) c The leading dimension of the array Z. If Ritz vectors are c desired, then LDZ .ge. max( 1, N ) is required. c In any case, LDZ .ge. 1 is required. c c SIGMA Complex*16 (INPUT) c If IPARAM(7) = 3 then SIGMA represents the shift. c Not referenced if IPARAM(7) = 1 or 2. c c WORKEV Complex*16 work array of dimension 2*NCV. (WORKSPACE) c c **** The remaining arguments MUST be the same as for the **** c **** call to ZNAUPD that was just completed. **** c c NOTE: The remaining arguments c c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, c WORKD, WORKL, LWORKL, RWORK, INFO c c must be passed directly to ZNEUPD following the last call c to ZNAUPD. These arguments MUST NOT BE MODIFIED between c the the last call to ZNAUPD and the call to ZNEUPD. c c Three of these parameters (V, WORKL and INFO) are also output parameters: c c V Complex*16 N by NCV array. (INPUT/OUTPUT) c c Upon INPUT: the NCV columns of V contain the Arnoldi basis c vectors for OP as constructed by ZNAUPD . c c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns c contain approximate Schur vectors that span the c desired invariant subspace. c c NOTE: If the array Z has been set equal to first NEV+1 columns c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the c Arnoldi basis held by V has been overwritten by the desired c Ritz vectors. If a separate array Z has been passed then c the first NCONV=IPARAM(5) columns of V will contain approximate c Schur vectors that span the desired invariant subspace. c c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE) c WORKL(1:ncv*ncv+2*ncv) contains information obtained in c znaupd. They are not changed by zneupd. c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the c untransformed Ritz values, the untransformed error estimates of c the Ritz values, the upper triangular matrix for H, and the c associated matrix representation of the invariant subspace for H. c c Note: IPNTR(9:13) contains the pointer into WORKL for addresses c of the above information computed by zneupd. c ------------------------------------------------------------- c IPNTR(9): pointer to the NCV RITZ values of the c original system. c IPNTR(10): Not used c IPNTR(11): pointer to the NCV corresponding error estimates. c IPNTR(12): pointer to the NCV by NCV upper triangular c Schur matrix for H. c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors c of the upper Hessenberg matrix H. Only referenced by c zneupd if RVEC = .TRUE. See Remark 2 below. c ------------------------------------------------------------- c c INFO Integer. (OUTPUT) c Error flag on output. c = 0: Normal exit. c c = 1: The Schur form computed by LAPACK routine csheqr c could not be reordered by LAPACK routine ztrsen. c Re-enter subroutine zneupd with IPARAM(5)=NCV and c increase the size of the array D to have c dimension at least dimension NCV and allocate at least NCV c columns for Z. NOTE: Not necessary if Z and V share c the same space. Please notify the authors if this error c occurs. c c = -1: N must be positive. c = -2: NEV must be positive. c = -3: NCV-NEV >= 1 and less than or equal to N. c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI' c = -6: BMAT must be one of 'I' or 'G'. c = -7: Length of private work WORKL array is not sufficient. c = -8: Error return from LAPACK eigenvalue calculation. c This should never happened. c = -9: Error return from calculation of eigenvectors. c Informational error from LAPACK routine ztrevc. c = -10: IPARAM(7) must be 1,2,3 c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible. c = -12: HOWMNY = 'S' not yet implemented c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true. c = -14: ZNAUPD did not find any eigenvalues to sufficient c accuracy. c = -15: ZNEUPD got a different count of the number of converged c Ritz values than ZNAUPD got. This indicates the user c probably made an error in passing data from ZNAUPD to c ZNEUPD or that the data was modified before entering c ZNEUPD c c\BeginLib c c\References: c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992), c pp 357-385. c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly c Restarted Arnoldi Iteration", Rice University Technical Report c TR95-13, Department of Computational and Applied Mathematics. c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen, c "How to Implement the Spectral Transformation", Math Comp., c Vol. 48, No. 178, April, 1987 pp. 664-673. c c\Routines called: c ivout ARPACK utility routine that prints integers. c zmout ARPACK utility routine that prints matrices c zvout ARPACK utility routine that prints vectors. c zgeqr2 LAPACK routine that computes the QR factorization of c a matrix. c zlacpy LAPACK matrix copy routine. c zlahqr LAPACK routine that computes the Schur form of a c upper Hessenberg matrix. c zlaset LAPACK matrix initialization routine. c ztrevc LAPACK routine to compute the eigenvectors of a matrix c in upper triangular form. c ztrsen LAPACK routine that re-orders the Schur form. c zunm2r LAPACK routine that applies an orthogonal matrix in c factored form. c dlamch LAPACK routine that determines machine constants. c ztrmm Level 3 BLAS matrix times an upper triangular matrix. c zgeru Level 2 BLAS rank one update to a matrix. c zcopy Level 1 BLAS that copies one vector to another . c zscal Level 1 BLAS that scales a vector. c zdscal Level 1 BLAS that scales a complex vector by a real number. c dznrm2 Level 1 BLAS that computes the norm of a complex vector. c c\Remarks c c 1. Currently only HOWMNY = 'A' and 'P' are implemented. c c 2. Schur vectors are an orthogonal representation for the basis of c Ritz vectors. Thus, their numerical properties are often superior. c If RVEC = .true. then the relationship c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and c transpose( V(:,1:IPARAM(5)) ) * V(:,1:IPARAM(5)) = I c are approximately satisfied. c Here T is the leading submatrix of order IPARAM(5) of the c upper triangular matrix stored workl(ipntr(12)). c c\Authors c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Chao Yang Houston, Texas c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: neupd.F SID: 2.8 DATE OF SID: 07/21/02 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- subroutine zneupd(rvec , howmny, select, d , & z , ldz , sigma , workev, & bmat , n , which , nev , & tol , resid , ncv , v , & ldv , iparam, ipntr , workd , & workl, lworkl, rwork , info ) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character bmat, howmny, which*2 logical rvec integer info, ldz, ldv, lworkl, n, ncv, nev Complex*16 & sigma Double precision & tol c c %-----------------% c | Array Arguments | c %-----------------% c integer iparam(11), ipntr(14) logical select(ncv) Double precision & rwork(ncv) Complex*16 & d(nev) , resid(n) , v(ldv,ncv), & z(ldz, nev), & workd(3*n) , workl(lworkl), workev(2*ncv) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0)) c c %---------------% c | Local Scalars | c %---------------% c character type*6 integer bounds, ierr , ih , ihbds, iheig , nconv , & invsub, iuptri, iwev , j , ldh , ldq , & mode , msglvl, ritz , wr , k , irz , & ibd , outncv, iq , np , numcnv, jj , & ishift, nconv2 Complex*16 & rnorm, temp, vl(1) Double precision & conds, sep, rtemp, eps23 logical reord c c %----------------------% c | External Subroutines | c %----------------------% c external zcopy , zgeru, zgeqr2, zlacpy, zmout, & zunm2r, ztrmm, zvout, ivout, & zlahqr c c %--------------------% c | External Functions | c %--------------------% c Double precision & dznrm2, dlamch, dlapy2 external dznrm2, dlamch, dlapy2 c Complex*16 & zdotc external zdotc c c %-----------------------% c | Executable Statements | c %-----------------------% c c %------------------------% c | Set default parameters | c %------------------------% c msglvl = mceupd mode = iparam(7) nconv = iparam(5) info = 0 c c c %---------------------------------% c | Get machine dependent constant. | c %---------------------------------% c eps23 = dlamch('Epsilon-Machine') eps23 = eps23**(2.0D+0 / 3.0D+0) c c %-------------------------------% c | Quick return | c | Check for incompatible input | c %-------------------------------% c ierr = 0 c if (nconv .le. 0) then ierr = -14 else if (n .le. 0) then ierr = -1 else if (nev .le. 0) then ierr = -2 else if (ncv .le. nev+1 .or. ncv .gt. n) then ierr = -3 else if (which .ne. 'LM' .and. & which .ne. 'SM' .and. & which .ne. 'LR' .and. & which .ne. 'SR' .and. & which .ne. 'LI' .and. & which .ne. 'SI') then ierr = -5 else if (bmat .ne. 'I' .and. bmat .ne. 'G') then ierr = -6 else if (lworkl .lt. 3*ncv**2 + 4*ncv) then ierr = -7 else if ( (howmny .ne. 'A' .and. & howmny .ne. 'P' .and. & howmny .ne. 'S') .and. rvec ) then ierr = -13 else if (howmny .eq. 'S' ) then ierr = -12 end if c if (mode .eq. 1 .or. mode .eq. 2) then type = 'REGULR' else if (mode .eq. 3 ) then type = 'SHIFTI' else ierr = -10 end if if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11 c c %------------% c | Error Exit | c %------------% c if (ierr .ne. 0) then info = ierr go to 9000 end if c c %--------------------------------------------------------% c | Pointer into WORKL for address of H, RITZ, WORKEV, Q | c | etc... and the remaining workspace. | c | Also update pointer to be used on output. | c | Memory is laid out as follows: | c | workl(1:ncv*ncv) := generated Hessenberg matrix | c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values | c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds | c %--------------------------------------------------------% c c %-----------------------------------------------------------% c | The following is used and set by ZNEUPD. | c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed | c | Ritz values. | c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed | c | error bounds of | c | the Ritz values | c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper | c | triangular matrix | c | for H. | c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the | c | associated matrix | c | representation of | c | the invariant | c | subspace for H. | c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. | c %-----------------------------------------------------------% c ih = ipntr(5) ritz = ipntr(6) iq = ipntr(7) bounds = ipntr(8) ldh = ncv ldq = ncv iheig = bounds + ldh ihbds = iheig + ldh iuptri = ihbds + ldh invsub = iuptri + ldh*ncv ipntr(9) = iheig ipntr(11) = ihbds ipntr(12) = iuptri ipntr(13) = invsub wr = 1 iwev = wr + ncv c c %-----------------------------------------% c | irz points to the Ritz values computed | c | by _neigh before exiting _naup2. | c | ibd points to the Ritz estimates | c | computed by _neigh before exiting | c | _naup2. | c %-----------------------------------------% c irz = ipntr(14) + ncv*ncv ibd = irz + ncv c c %------------------------------------% c | RNORM is B-norm of the RESID(1:N). | c %------------------------------------% c rnorm = workl(ih+2) workl(ih+2) = zero c if (msglvl .gt. 2) then call zvout(logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values passed in from _NAUPD.') call zvout(logfil, ncv, workl(ibd), ndigit, & '_neupd: Ritz estimates passed in from _NAUPD.') end if c if (rvec) then c reord = .false. c c %---------------------------------------------------% c | Use the temporary bounds array to store indices | c | These will be used to mark the select array later | c %---------------------------------------------------% c do 10 j = 1,ncv workl(bounds+j-1) = j select(j) = .false. 10 continue c c %-------------------------------------% c | Select the wanted Ritz values. | c | Sort the Ritz values so that the | c | wanted ones appear at the tailing | c | NEV positions of workl(irr) and | c | workl(iri). Move the corresponding | c | error estimates in workl(ibd) | c | accordingly. | c %-------------------------------------% c np = ncv - nev ishift = 0 call zngets(ishift, which , nev , & np , workl(irz), workl(bounds)) c if (msglvl .gt. 2) then call zvout (logfil, ncv, workl(irz), ndigit, & '_neupd: Ritz values after calling _NGETS.') call zvout (logfil, ncv, workl(bounds), ndigit, & '_neupd: Ritz value indices after calling _NGETS.') end if c c %-----------------------------------------------------% c | Record indices of the converged wanted Ritz values | c | Mark the select array for possible reordering | c %-----------------------------------------------------% c numcnv = 0 do 11 j = 1,ncv rtemp = max(eps23, & dlapy2 ( dble(workl(irz+ncv-j)), & dimag(workl(irz+ncv-j)) )) jj = workl(bounds + ncv - j) if (numcnv .lt. nconv .and. & dlapy2( dble(workl(ibd+jj-1)), & dimag(workl(ibd+jj-1)) ) & .le. tol*rtemp) then select(jj) = .true. numcnv = numcnv + 1 if (jj .gt. nconv) reord = .true. endif 11 continue c c %-----------------------------------------------------------% c | Check the count (numcnv) of converged Ritz values with | c | the number (nconv) reported by dnaupd. If these two | c | are different then there has probably been an error | c | caused by incorrect passing of the dnaupd data. | c %-----------------------------------------------------------% c if (msglvl .gt. 2) then call ivout(logfil, 1, numcnv, ndigit, & '_neupd: Number of specified eigenvalues') call ivout(logfil, 1, nconv, ndigit, & '_neupd: Number of "converged" eigenvalues') end if c if (numcnv .ne. nconv) then info = -15 go to 9000 end if c c %-------------------------------------------------------% c | Call LAPACK routine zlahqr to compute the Schur form | c | of the upper Hessenberg matrix returned by ZNAUPD. | c | Make a copy of the upper Hessenberg matrix. | c | Initialize the Schur vector matrix Q to the identity. | c %-------------------------------------------------------% c call zcopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1) call zlaset('All', ncv, ncv , & zero , one, workl(invsub), & ldq) call zlahqr(.true., .true. , ncv , & 1 , ncv , workl(iuptri), & ldh , workl(iheig) , 1 , & ncv , workl(invsub), ldq , & ierr) call zcopy(ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c if (ierr .ne. 0) then info = -8 go to 9000 end if c if (msglvl .gt. 1) then call zvout (logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H') call zvout (logfil, ncv, workl(ihbds), ndigit, & '_neupd: Last row of the Schur vector matrix') if (msglvl .gt. 3) then call zmout (logfil , ncv, ncv , & workl(iuptri), ldh, ndigit, & '_neupd: The upper triangular matrix ') end if end if c if (reord) then c c %-----------------------------------------------% c | Reorder the computed upper triangular matrix. | c %-----------------------------------------------% c call ztrsen('None' , 'V' , select , & ncv , workl(iuptri), ldh , & workl(invsub), ldq , workl(iheig), & nconv2 , conds , sep , & workev , ncv , ierr) c if (nconv2 .lt. nconv) then nconv = nconv2 end if if (ierr .eq. 1) then info = 1 go to 9000 end if c if (msglvl .gt. 2) then call zvout (logfil, ncv, workl(iheig), ndigit, & '_neupd: Eigenvalues of H--reordered') if (msglvl .gt. 3) then call zmout(logfil , ncv, ncv , & workl(iuptri), ldq, ndigit, & '_neupd: Triangular matrix after re-ordering') end if end if c end if c c %---------------------------------------------% c | Copy the last row of the Schur basis matrix | c | to workl(ihbds). This vector will be used | c | to compute the Ritz estimates of converged | c | Ritz values. | c %---------------------------------------------% c call zcopy(ncv , workl(invsub+ncv-1), ldq, & workl(ihbds), 1) c c %--------------------------------------------% c | Place the computed eigenvalues of H into D | c | if a spectral transformation was not used. | c %--------------------------------------------% c if (type .eq. 'REGULR') then call zcopy(nconv, workl(iheig), 1, d, 1) end if c c %----------------------------------------------------------% c | Compute the QR factorization of the matrix representing | c | the wanted invariant subspace located in the first NCONV | c | columns of workl(invsub,ldq). | c %----------------------------------------------------------% c call zgeqr2(ncv , nconv , workl(invsub), & ldq , workev, workev(ncv+1), & ierr) c c %--------------------------------------------------------% c | * Postmultiply V by Q using zunm2r. | c | * Copy the first NCONV columns of VQ into Z. | c | * Postmultiply Z by R. | c | The N by NCONV matrix Z is now a matrix representation | c | of the approximate invariant subspace associated with | c | the Ritz values in workl(iheig). The first NCONV | c | columns of V are now approximate Schur vectors | c | associated with the upper triangular matrix of order | c | NCONV in workl(iuptri). | c %--------------------------------------------------------% c call zunm2r('Right', 'Notranspose', n , & ncv , nconv , workl(invsub), & ldq , workev , v , & ldv , workd(n+1) , ierr) call zlacpy('All', n, nconv, v, ldv, z, ldz) c do 20 j=1, nconv c c %---------------------------------------------------% c | Perform both a column and row scaling if the | c | diagonal element of workl(invsub,ldq) is negative | c | I'm lazy and don't take advantage of the upper | c | triangular form of workl(iuptri,ldq). | c | Note that since Q is orthogonal, R is a diagonal | c | matrix consisting of plus or minus ones. | c %---------------------------------------------------% c if ( dble( workl(invsub+(j-1)*ldq+j-1) ) .lt. & dble(zero) ) then call zscal(nconv, -one, workl(iuptri+j-1), ldq) call zscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1) end if c 20 continue c if (howmny .eq. 'A') then c c %--------------------------------------------% c | Compute the NCONV wanted eigenvectors of T | c | located in workl(iuptri,ldq). | c %--------------------------------------------% c do 30 j=1, ncv if (j .le. nconv) then select(j) = .true. else select(j) = .false. end if 30 continue c call ztrevc('Right', 'Select' , select , & ncv , workl(iuptri), ldq , & vl , 1 , workl(invsub), & ldq , ncv , outncv , & workev , rwork , ierr) c if (ierr .ne. 0) then info = -9 go to 9000 end if c c %------------------------------------------------% c | Scale the returning eigenvectors so that their | c | Euclidean norms are all one. LAPACK subroutine | c | ztrevc returns each eigenvector normalized so | c | that the element of largest magnitude has | c | magnitude 1. | c %------------------------------------------------% c do 40 j=1, nconv rtemp = dznrm2(ncv, workl(invsub+(j-1)*ldq), 1) rtemp = dble(one) / rtemp call zdscal ( ncv, rtemp, & workl(invsub+(j-1)*ldq), 1 ) c c %------------------------------------------% c | Ritz estimates can be obtained by taking | c | the inner product of the last row of the | c | Schur basis of H with eigenvectors of T. | c | Note that the eigenvector matrix of T is | c | upper triangular, thus the length of the | c | inner product can be set to j. | c %------------------------------------------% c workev(j) = zdotc(j, workl(ihbds), 1, & workl(invsub+(j-1)*ldq), 1) 40 continue c if (msglvl .gt. 2) then call zcopy(nconv, workl(invsub+ncv-1), ldq, & workl(ihbds), 1) call zvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Last row of the eigenvector matrix for T') if (msglvl .gt. 3) then call zmout(logfil , ncv, ncv , & workl(invsub), ldq, ndigit, & '_neupd: The eigenvector matrix for T') end if end if c c %---------------------------------------% c | Copy Ritz estimates into workl(ihbds) | c %---------------------------------------% c call zcopy(nconv, workev, 1, workl(ihbds), 1) c c %----------------------------------------------% c | The eigenvector matrix Q of T is triangular. | c | Form Z*Q. | c %----------------------------------------------% c call ztrmm('Right' , 'Upper' , 'No transpose', & 'Non-unit', n , nconv , & one , workl(invsub), ldq , & z , ldz) end if c else c c %--------------------------------------------------% c | An approximate invariant subspace is not needed. | c | Place the Ritz values computed ZNAUPD into D. | c %--------------------------------------------------% c call zcopy(nconv, workl(ritz), 1, d, 1) call zcopy(nconv, workl(ritz), 1, workl(iheig), 1) call zcopy(nconv, workl(bounds), 1, workl(ihbds), 1) c end if c c %------------------------------------------------% c | Transform the Ritz values and possibly vectors | c | and corresponding error bounds of OP to those | c | of A*x = lambda*B*x. | c %------------------------------------------------% c if (type .eq. 'REGULR') then c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c else c c %---------------------------------------% c | A spectral transformation was used. | c | * Determine the Ritz estimates of the | c | Ritz values in the original system. | c %---------------------------------------% c if (rvec) & call zscal(ncv, rnorm, workl(ihbds), 1) c do 50 k=1, ncv temp = workl(iheig+k-1) workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp 50 continue c end if c c %-----------------------------------------------------------% c | * Transform the Ritz values back to the original system. | c | For TYPE = 'SHIFTI' the transformation is | c | lambda = 1/theta + sigma | c | NOTES: | c | *The Ritz vectors are not affected by the transformation. | c %-----------------------------------------------------------% c if (type .eq. 'SHIFTI') then do 60 k=1, nconv d(k) = one / workl(iheig+k-1) + sigma 60 continue end if c if (type .ne. 'REGULR' .and. msglvl .gt. 1) then call zvout (logfil, nconv, d, ndigit, & '_neupd: Untransformed Ritz values.') call zvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Ritz estimates of the untransformed Ritz values.') else if ( msglvl .gt. 1) then call zvout (logfil, nconv, d, ndigit, & '_neupd: Converged Ritz values.') call zvout (logfil, nconv, workl(ihbds), ndigit, & '_neupd: Associated Ritz estimates.') end if c c %-------------------------------------------------% c | Eigenvector Purification step. Formally perform | c | one of inverse subspace iteration. Only used | c | for MODE = 3. See reference 3. | c %-------------------------------------------------% c if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then c c %------------------------------------------------% c | Purify the computed Ritz vectors by adding a | c | little bit of the residual vector: | c | T | c | resid(:)*( e s ) / theta | c | NCV | c | where H s = s theta. | c %------------------------------------------------% c do 100 j=1, nconv if (workl(iheig+j-1) .ne. zero) then workev(j) = workl(invsub+(j-1)*ldq+ncv-1) / & workl(iheig+j-1) endif 100 continue c %---------------------------------------% c | Perform a rank one update to Z and | c | purify all the Ritz vectors together. | c %---------------------------------------% c call zgeru (n, nconv, one, resid, 1, workev, 1, z, ldz) c end if c 9000 continue c return c c %---------------% c | End of zneupd| c %---------------% c end arpack-ng-3.3.0/SRC/zngets.f000066400000000000000000000127121260666001200154720ustar00rootroot00000000000000c\BeginDoc c c\Name: zngets c c\Description: c Given the eigenvalues of the upper Hessenberg matrix H, c computes the NP shifts AMU that are zeros of the polynomial of c degree NP which filters out components of the unwanted eigenvectors c corresponding to the AMU's based on some given criteria. c c NOTE: call this even in the case of user specified shifts in order c to sort the eigenvalues, and error bounds of H for later use. c c\Usage: c call zngets c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS ) c c\Arguments c ISHIFT Integer. (INPUT) c Method for selecting the implicit shifts at each iteration. c ISHIFT = 0: user specified shifts c ISHIFT = 1: exact shift with respect to the matrix H. c c WHICH Character*2. (INPUT) c Shift selection criteria. c 'LM' -> want the KEV eigenvalues of largest magnitude. c 'SM' -> want the KEV eigenvalues of smallest magnitude. c 'LR' -> want the KEV eigenvalues of largest REAL part. c 'SR' -> want the KEV eigenvalues of smallest REAL part. c 'LI' -> want the KEV eigenvalues of largest imaginary part. c 'SI' -> want the KEV eigenvalues of smallest imaginary part. c c KEV Integer. (INPUT) c The number of desired eigenvalues. c c NP Integer. (INPUT) c The number of shifts to compute. c c RITZ Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c On INPUT, RITZ contains the the eigenvalues of H. c On OUTPUT, RITZ are sorted so that the unwanted c eigenvalues are in the first NP locations and the wanted c portion is in the last KEV locations. When exact shifts are c selected, the unwanted part corresponds to the shifts to c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues c are further sorted so that the ones with largest Ritz values c are first. c c BOUNDS Complex*16 array of length KEV+NP. (INPUT/OUTPUT) c Error bounds corresponding to the ordering in RITZ. c c c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Local variables: c xxxxxx Complex*16 c c\Routines called: c zsortc ARPACK sorting routine. c ivout ARPACK utility routine that prints integers. c arscnd ARPACK utility routine for timing. c zvout ARPACK utility routine that prints vectors. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: ngets.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\Remarks c 1. This routine does not keep complex conjugate pairs of c eigenvalues together. c c\EndLib c c----------------------------------------------------------------------- c subroutine zngets ( ishift, which, kev, np, ritz, bounds) c c %----------------------------------------------------% c | Include files for debugging and timing information | c %----------------------------------------------------% c include 'debug.h' include 'stat.h' c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which integer ishift, kev, np c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & bounds(kev+np), ritz(kev+np) c c %------------% c | Parameters | c %------------% c Complex*16 & one, zero parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0)) c c %---------------% c | Local Scalars | c %---------------% c integer msglvl c c %----------------------% c | External Subroutines | c %----------------------% c external zvout, zsortc, arscnd c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------% c | Initialize timing statistics | c | & message level for debugging | c %-------------------------------% c call arscnd (t0) msglvl = mcgets c call zsortc (which, .true., kev+np, ritz, bounds) c if ( ishift .eq. 1 ) then c c %-------------------------------------------------------% c | Sort the unwanted Ritz values used as shifts so that | c | the ones with largest Ritz estimates are first | c | This will tend to minimize the effects of the | c | forward instability of the iteration when the shifts | c | are applied in subroutine znapps. | c | Be careful and use 'SM' since we want to sort BOUNDS! | c %-------------------------------------------------------% c call zsortc ( 'SM', .true., np, bounds, ritz ) c end if c call arscnd (t1) tcgets = tcgets + (t1 - t0) c if (msglvl .gt. 0) then call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is') call ivout (logfil, 1, np, ndigit, '_ngets: NP is') call zvout (logfil, kev+np, ritz, ndigit, & '_ngets: Eigenvalues of current H matrix ') call zvout (logfil, kev+np, bounds, ndigit, & '_ngets: Ritz estimates of the current KEV+NP Ritz values') end if c return c c %---------------% c | End of zngets | c %---------------% c end arpack-ng-3.3.0/SRC/zsortc.f000066400000000000000000000176601260666001200155130ustar00rootroot00000000000000c\BeginDoc c c\Name: zsortc c c\Description: c Sorts the Complex*16 array in X into the order c specified by WHICH and optionally applies the permutation to the c Double precision array Y. c c\Usage: c call zsortc c ( WHICH, APPLY, N, X, Y ) c c\Arguments c WHICH Character*2. (Input) c 'LM' -> sort X into increasing order of magnitude. c 'SM' -> sort X into decreasing order of magnitude. c 'LR' -> sort X with real(X) in increasing algebraic order c 'SR' -> sort X with real(X) in decreasing algebraic order c 'LI' -> sort X with imag(X) in increasing algebraic order c 'SI' -> sort X with imag(X) in decreasing algebraic order c c APPLY Logical. (Input) c APPLY = .TRUE. -> apply the sorted order to array Y. c APPLY = .FALSE. -> do not apply the sorted order to array Y. c c N Integer. (INPUT) c Size of the arrays. c c X Complex*16 array of length N. (INPUT/OUTPUT) c This is the array to be sorted. c c Y Complex*16 array of length N. (INPUT/OUTPUT) c c\EndDoc c c----------------------------------------------------------------------- c c\BeginLib c c\Routines called: c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c c\Author c Danny Sorensen Phuong Vu c Richard Lehoucq CRPC / Rice University c Dept. of Computational & Houston, Texas c Applied Mathematics c Rice University c Houston, Texas c c Adapted from the sort routine in LANSO. c c\SCCS Information: @(#) c FILE: sortc.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c\EndLib c c----------------------------------------------------------------------- c subroutine zsortc (which, apply, n, x, y) c c %------------------% c | Scalar Arguments | c %------------------% c character*2 which logical apply integer n c c %-----------------% c | Array Arguments | c %-----------------% c Complex*16 & x(0:n-1), y(0:n-1) c c %---------------% c | Local Scalars | c %---------------% c integer i, igap, j Complex*16 & temp Double precision & temp1, temp2 c c %--------------------% c | External functions | c %--------------------% c Double precision & dlapy2 c c %--------------------% c | Intrinsic Functions | c %--------------------% Intrinsic & dble, dimag c c %-----------------------% c | Executable Statements | c %-----------------------% c igap = n / 2 c if (which .eq. 'LM') then c c %--------------------------------------------% c | Sort X into increasing order of magnitude. | c %--------------------------------------------% c 10 continue if (igap .eq. 0) go to 9000 c do 30 i = igap, n-1 j = i-igap 20 continue c if (j.lt.0) go to 30 c temp1 = dlapy2(dble(x(j)),dimag(x(j))) temp2 = dlapy2(dble(x(j+igap)),dimag(x(j+igap))) c if (temp1.gt.temp2) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 30 end if j = j-igap go to 20 30 continue igap = igap / 2 go to 10 c else if (which .eq. 'SM') then c c %--------------------------------------------% c | Sort X into decreasing order of magnitude. | c %--------------------------------------------% c 40 continue if (igap .eq. 0) go to 9000 c do 60 i = igap, n-1 j = i-igap 50 continue c if (j .lt. 0) go to 60 c temp1 = dlapy2(dble(x(j)),dimag(x(j))) temp2 = dlapy2(dble(x(j+igap)),dimag(x(j+igap))) c if (temp1.lt.temp2) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 60 endif j = j-igap go to 50 60 continue igap = igap / 2 go to 40 c else if (which .eq. 'LR') then c c %------------------------------------------------% c | Sort XREAL into increasing order of algebraic. | c %------------------------------------------------% c 70 continue if (igap .eq. 0) go to 9000 c do 90 i = igap, n-1 j = i-igap 80 continue c if (j.lt.0) go to 90 c if (dble(x(j)).gt.dble(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 90 endif j = j-igap go to 80 90 continue igap = igap / 2 go to 70 c else if (which .eq. 'SR') then c c %------------------------------------------------% c | Sort XREAL into decreasing order of algebraic. | c %------------------------------------------------% c 100 continue if (igap .eq. 0) go to 9000 do 120 i = igap, n-1 j = i-igap 110 continue c if (j.lt.0) go to 120 c if (dble(x(j)).lt.dble(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 120 endif j = j-igap go to 110 120 continue igap = igap / 2 go to 100 c else if (which .eq. 'LI') then c c %--------------------------------------------% c | Sort XIMAG into increasing algebraic order | c %--------------------------------------------% c 130 continue if (igap .eq. 0) go to 9000 do 150 i = igap, n-1 j = i-igap 140 continue c if (j.lt.0) go to 150 c if (dimag(x(j)).gt.dimag(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 150 endif j = j-igap go to 140 150 continue igap = igap / 2 go to 130 c else if (which .eq. 'SI') then c c %---------------------------------------------% c | Sort XIMAG into decreasing algebraic order | c %---------------------------------------------% c 160 continue if (igap .eq. 0) go to 9000 do 180 i = igap, n-1 j = i-igap 170 continue c if (j.lt.0) go to 180 c if (dimag(x(j)).lt.dimag(x(j+igap))) then temp = x(j) x(j) = x(j+igap) x(j+igap) = temp c if (apply) then temp = y(j) y(j) = y(j+igap) y(j+igap) = temp end if else go to 180 endif j = j-igap go to 170 180 continue igap = igap / 2 go to 160 end if c 9000 continue return c c %---------------% c | End of zsortc | c %---------------% c end arpack-ng-3.3.0/SRC/zstatn.f000066400000000000000000000023051260666001200155000ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: statn.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2 c c %---------------------------------------------% c | Initialize statistic and timing information | c | for complex nonsymmetric Arnoldi code. | c %---------------------------------------------% subroutine zstatn c c %--------------------------------% c | See stat.doc for documentation | c %--------------------------------% c include 'stat.h' c %-----------------------% c | Executable Statements | c %-----------------------% nopx = 0 nbx = 0 nrorth = 0 nitref = 0 nrstrt = 0 tcaupd = 0.0D+0 tcaup2 = 0.0D+0 tcaitr = 0.0D+0 tceigh = 0.0D+0 tcgets = 0.0D+0 tcapps = 0.0D+0 tcconv = 0.0D+0 titref = 0.0D+0 tgetv0 = 0.0D+0 trvec = 0.0D+0 c %----------------------------------------------------% c | User time including reverse communication overhead | c %----------------------------------------------------% tmvopx = 0.0D+0 tmvbx = 0.0D+0 return c c %---------------% c | End of zstatn | c %---------------% c end arpack-ng-3.3.0/TESTS/000077500000000000000000000000001260666001200142615ustar00rootroot00000000000000arpack-ng-3.3.0/TESTS/Makefile.am000066400000000000000000000006461260666001200163230ustar00rootroot00000000000000LDADD=$(top_builddir)/libarpack.la $(BLAS_LIBS) $(LAPACK_LIBS) AM_DEFAULT_SOURCE_EXT = .f check_PROGRAMS = dnsimp bug_1315_single bug_1315_double bug_1323 TESTS = test-dnsimp.sh bug_1315_single bug_1315_double bug_1323 EXTRA_DIST = testA.mtx test-dnsimp.sh dnsimp_SOURCES = dnsimp.f mmio.f debug.h bug_1315_single_SOURCES = bug_1315_single.c bug_1315_double_SOURCES = bug_1315_double.c bug_1323_SOURCES = bug_1323.f arpack-ng-3.3.0/TESTS/bug_1315_double.c000066400000000000000000000044711260666001200172130ustar00rootroot00000000000000#include #include #include /* test program to solve for the 9 largest eigenvalues of * A*x = lambda*x where A is the diagonal matrix * with entries 1000, 999, ... , 2, 1 on the diagonal. * We're using the non symmetric routines dnaupd and dneupd. * This is not efficient since the problem is * symmetric but is done to exhibit the bug. * */ extern void dnaupd_(int *, char *, int *, char *, int *, double *, double *, int *, double *, int *, int *, int *, double *, double *, int *, int *); extern void dneupd_( int*, char*, int *, double *, double *, double *, int*, double *, double *, double *, char *, int *, char *, int *, double *, double *, int *, double *, int *, int *, int *, double *, double *, int *, int * ); void matVec(double * x, double * y) { int i; for ( i = 0; i < 1000; ++i) y[i] = ((double) (i+1))*x[i]; }; int main() { int ido = 0; char bmat[] = "I"; int N = 1000; char which[] = "LM"; int nev = 9; double tol = 0; double resid[N]; int ncv = 2*nev+1; double V[ncv*N]; int ldv = N; int iparam[11]; int ipntr[14]; double workd[3*N]; int rvec = 1; char howmny[] = "A"; double* dr = (double*) malloc((nev+1)*sizeof(double)); double* di = (double*) malloc((nev+1)*sizeof(double)); int select[3*ncv]; double z[(N+1)*(nev+1)]; int ldz = N+1; double sigmar=0; double sigmai=0; double workev[3*ncv]; int k; for (k=0; k < 3*N; ++k ) workd[k] = 0; double workl[3*(ncv*ncv) + 6*ncv]; for (k=0; k < 3*(ncv*ncv) + 6*ncv; ++k ) workl[k] = 0; int lworkl = 3*(ncv*ncv) + 6*ncv; int info = 0; iparam[0] = 1; iparam[2] = 10*N; iparam[3] = 1; iparam[6] = 1; dnaupd_(&ido, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); while(ido == 1) { matVec(&(workd[ipntr[0]-1]), &(workd[ipntr[1]-1])); dnaupd_(&ido, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); } dneupd_( &rvec, howmny, select, dr,di, z, &ldz, &sigmar, &sigmai,workev, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); int i; for (i = 0; i < nev; ++i) { printf("%f\n", dr[i]); if(fabs(dr[i] - (double)(1000-i))>1e-6){ exit(EXIT_FAILURE); } } return 0; } arpack-ng-3.3.0/TESTS/bug_1315_single.c000066400000000000000000000044251260666001200172210ustar00rootroot00000000000000#include #include #include /* test program to solve for the 9 largest eigenvalues of * A*x = lambda*x where A is the diagonal matrix * with entries 1000, 999, ... , 2, 1 on the diagonal. * We're using the non symmetric routines dnaupd and dneupd. * This is not efficient since the problem is * symmetric but is done to exhibit the bug. */ extern void snaupd_(int *, char *, int *, char *, int *, float *, float *, int *, float *, int *, int *, int *, float *, float *, int *, int *); extern void sneupd_( int*, char*, int *, float *, float *, float *, int*, float *, float *, float *, char *, int *, char *, int *, float *, float *, int *, float *, int *, int *, int *, float *, float *, int *, int * ); void matVec(float * x, float * y) { int i; for ( i = 0; i < 1000; ++i) y[i] = ((float) (i+1))*x[i]; }; int main() { int ido = 0; char bmat[] = "I"; int N = 1000; char which[] = "LM"; int nev = 9; float tol = 0; float resid[N]; int ncv = 2*nev+1; float V[ncv*N]; int ldv = N; int iparam[11]; int ipntr[14]; float workd[3*N]; int rvec = 1; char howmny[] = "A"; float* dr = (float*) malloc((nev+1)*sizeof(float)); float* di = (float*) malloc((nev+1)*sizeof(float)); int select[3*ncv]; float z[(N+1)*(nev+1)]; int ldz = N+1; float sigmar=0; float sigmai=0; float workev[3*ncv]; int k; for (k=0; k < 3*N; ++k ) workd[k] = 0; float workl[3*(ncv*ncv) + 6*ncv]; for (k=0; k < 3*(ncv*ncv) + 6*ncv; ++k ) workl[k] = 0; int lworkl = 3*(ncv*ncv) + 6*ncv; int info = 0; iparam[0] = 1; iparam[2] = 10*N; iparam[3] = 1; iparam[6] = 1; snaupd_(&ido, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); while(ido == 1) { matVec(&(workd[ipntr[0]-1]), &(workd[ipntr[1]-1])); snaupd_(&ido, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); } sneupd_( &rvec, howmny, select, dr,di, z, &ldz, &sigmar, &sigmai,workev, bmat, &N, which, &nev, &tol, resid, &ncv, V, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); int i; for (i = 0; i < nev; ++i) { printf("%f\n", dr[i]); if(fabs(dr[i] - (float)(1000-i))>1e-2){ exit(EXIT_FAILURE); } } return 0; } arpack-ng-3.3.0/TESTS/bug_1323.f000066400000000000000000000352511260666001200156630ustar00rootroot00000000000000 program dseupd_bug_2 c c dsdrv2 program modified to reveal the bug in 'dseupd()': c c * 'implicit none' added c * rvec = .false. (don't want the eigenvectors) c * computation of the norm residual has been commented out c * 5th and 6th original arguments (v and ldv) have been replaced by c others (z and ldz) c * z is an allocatable array -- it is claimed that it is not referenced c * ldz = ldv -- fullfill the requirement that ldz .ge. 1 c c the following error is expected: c c Program received signal SIGSEGV: Segmentation fault - invalid memory reference. c Backtrace for this error: c ... c #3 0x428E36 in dger_ at dger.f:199 c #4 0x4099ED in dseupd_ at dseupd.f:852 (discriminator 4) c #5 0x401A71 in dseupd_bug_2 at dseupd_bug_2.f:301 c c É. Canot -- IRISA/CNRS -- Edouard.Canot@irisa.fr c______________________________________________________________________________ c c Program to illustrate the idea of reverse communication c in shift and invert mode for a standard symmetric eigenvalue c problem. The following program uses the two LAPACK subroutines c dgttrf.f and dgttrs.f to factor and solve a tridiagonal system of c equations. c c We implement example two of ex-sym.doc in DOCUMENTS directory c c\Example-2 c ... Suppose we want to solve A*x = lambda*x in shift-invert mode, c where A is derived from the central difference discretization c of the 1-dimensional Laplacian on [0,1] with zero Dirichlet c boundary condition. c ... OP = (inv[A - sigma*I]) and B = I. c ... Use mode 3 of DSAUPD. c c\BeginLib c c\Routines called: c dsaupd ARPACK reverse communication interface routine. c dseupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dgttrf LAPACK tridiagonal factorization routine. c dgttrs LAPACK tridiagonal solve routine. c daxpy daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: sdrv2.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c---------------------------------------------------------------------- c implicit none c c %-----------------------------% c | Define leading dimensions | c | for all arrays. | c | MAXN: Maximum dimension | c | of the A allowed. | c | MAXNEV: Maximum NEV allowed | c | MAXNCV: Maximum NCV allowed | c %-----------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=256, maxnev=10, maxncv=25, & ldv=maxn ) c c %--------------% c | Local Arrays | c %--------------% c Double precision & v(ldv,maxncv), workl(maxncv*(maxncv+8)), & workd(3*maxn), d(maxncv,2), resid(maxn), & ad(maxn), adl(maxn), adu(maxn), adu2(maxn), & ax(maxn) logical select(maxncv) integer iparam(11), ipntr(11), ipiv(maxn) double precision, allocatable :: z(:,:) integer :: ldz c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nev, ncv, lworkl, info, j, ierr, & nconv, maxitr, ishfts, mode logical rvec Double precision & sigma, tol, h2 c c %------------% c | Parameters | c %------------% c Double precision & zero, one, two parameter (zero = 0.0D+0, one = 1.0D+0, & two = 2.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dnrm2 external daxpy, dnrm2, dgttrf, dgttrs c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c %-----------------------% c | Executable Statements | c %-----------------------% c c %----------------------------------------------------% c | The number N is the dimension of the matrix. A | c | standard eigenvalue problem is solved (BMAT = 'I'. | c | NEV is the number of eigenvalues (closest to | c | SIGMA) to be approximated. Since the shift-invert | c | mode is used, WHICH is set to 'LM'. The user can | c | modify NEV, NCV, SIGMA to solve problems of | c | different sizes, and to get different parts of the | c | spectrum. However, The following conditions must | c | be satisfied: | c | N <= MAXN, | c | NEV <= MAXNEV, | c | NEV + 1 <= NCV <= MAXNCV | c %----------------------------------------------------% c n = 100 nev = 4 ncv = 10 if ( n .gt. maxn ) then print *, ' ERROR with _SDRV2: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _SDRV2: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _SDRV2: NCV is greater than MAXNCV ' go to 9000 end if c bmat = 'I' which = 'LM' sigma = zero c c %--------------------------------------------------% c | The work array WORKL is used in DSAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. The parameter TOL determines | c | the stopping criterion. If TOL<=0, machine | c | precision is used. The variable IDO is used for | c | reverse communication and is initially set to 0. | c | Setting INFO=0 indicates that a random vector is | c | generated in DSAUPD to start the Arnoldi | c | iteration. | c %--------------------------------------------------% c lworkl = ncv*(ncv+8) tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | This program uses exact shifts with respect to | c | the current Hessenberg matrix (IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 3 of DSAUPD is used | c | (IPARAM(7) = 3). All these options may be | c | changed by the user. For details, see the | c | documentation in DSAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 300 mode = 3 c iparam(1) = ishfts iparam(3) = maxitr iparam(7) = mode c c %-----------------------------------------------------% c | Call LAPACK routine to factor (A-SIGMA*I), where A | c | is the 1-d Laplacian. | c %-----------------------------------------------------% c h2 = one / dble((n+1)*(n+1)) do 20 j=1,n ad(j) = two / h2 - sigma adl(j) = -one / h2 20 continue call dcopy (n, adl, 1, adu, 1) call dgttrf (n, adl, ad, adu, adu2, ipiv, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrf in SDRV2.' print *, ' ' go to 9000 end if c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DSAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dsaupd ( ido, bmat, n, which, nev, tol, resid, & ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %----------------------------------------% c | Perform y <-- OP*x = inv[A-sigma*I]*x. | c | The user only need the linear system | c | solver here that takes workd(ipntr(1)) | c | as input, and returns the result to | c | workd(ipntr(2)). | c %----------------------------------------% c call dcopy (n, workd(ipntr(1)), 1, workd(ipntr(2)), 1) c call dgttrs ('Notranspose', n, 1, adl, ad, adu, adu2, ipiv, & workd(ipntr(2)), n, ierr) if (ierr .ne. 0) then print *, ' ' print *, ' Error with _gttrs in _SDRV2. ' print *, ' ' go to 9000 end if c c %-----------------------------------------% c | L O O P B A C K to call DSAUPD again. | c %-----------------------------------------% c go to 10 c end if c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %----------------------------% c | Error message. Check the | c | documentation in DSAUPD | c %----------------------------% c print *, ' ' print *, ' Error with _saupd, info = ',info print *, ' Check documentation of _saupd ' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DSEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may also be computed now if | c | desired. (indicated by rvec = .true.) | c %-------------------------------------------% c rvec = .false. ldz = ldv c call dseupd ( rvec, 'All', select, d, z, ldz, sigma, & bmat, n, which, nev, tol, resid, ncv, v, ldv, & iparam, ipntr, workd, workl, lworkl, ierr ) c c %----------------------------------------------% c | Eigenvalues are returned in the first column | c | of the two dimensional array D and the | c | corresponding eigenvectors are returned in | c | the first NEV columns of the two dimensional | c | array V if requested. Otherwise, an | c | orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %----------------------------------------------% if ( ierr .ne. 0 ) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DSEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _seupd, info = ', ierr print *, ' Check the documentation of _seupd ' print *, ' ' c else c nconv = iparam(5) CC do 30 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (iparam(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c CC call av(n, v(1,j), ax) CC call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) CC d(j,2) = dnrm2(n, ax, 1) CC d(j,2) = d(j,2) / abs(d(j,1)) c CC 30 continue c c %-------------------------------% c | Display computed residuals | c %-------------------------------% c call dmout(6, nconv, 2, d, maxncv, -6, & 'Ritz values and relative residuals') end if c c %------------------------------------------% c | Print additional convergence information | c %------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _SDRV2 ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dsdrv2. | c %---------------------------% c 9000 continue c end c c------------------------------------------------------------------------ c Matrix vector subroutine c where the matrix is the 1 dimensional discrete Laplacian on c the interval [0,1] with zero Dirichlet boundary condition. c subroutine av (n, v, w) integer n, j Double precision & v(n), w(n), one, two, h2 parameter (one = 1.0D+0, two = 2.0D+0) c w(1) = two*v(1) - v(2) do 100 j = 2,n-1 w(j) = - v(j-1) + two*v(j) - v(j+1) 100 continue j = n w(j) = - v(j-1) + two*v(j) c c Scale the vector w by (1 / h^2). c h2 = one / dble((n+1)*(n+1)) call dscal(n, one/h2, w, 1) return end arpack-ng-3.3.0/TESTS/debug.h000066400000000000000000000013511260666001200155200ustar00rootroot00000000000000c c\SCCS Information: @(#) c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2 c c %---------------------------------% c | See debug.doc for documentation | c %---------------------------------% integer logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd common /debug/ & logfil, ndigit, mgetv0, & msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd, & mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd, & mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd arpack-ng-3.3.0/TESTS/dnsimp.f000066400000000000000000000504621260666001200157310ustar00rootroot00000000000000 program dnsimp c c c This example program is intended to illustrate the c simplest case of using ARPACK in considerable detail. c This code may be used to understand basic usage of ARPACK c and as a template for creating an interface to ARPACK. c c This code shows how to use ARPACK to find a few eigenvalues c (lambda) and corresponding eigenvectors (x) for the standard c eigenvalue problem: c c A*x = lambda*x c c where A is a n by n real nonsymmetric matrix. c c The main points illustrated here are c c 1) How to declare sufficient memory to find NEV c eigenvalues of largest magnitude. Other options c are available. c c 2) Illustration of the reverse communication interface c needed to utilize the top level ARPACK routine DNAUPD c that computes the quantities needed to construct c the desired eigenvalues and eigenvectors(if requested). c c 3) How to extract the desired eigenvalues and eigenvectors c using the ARPACK routine DNEUPD. c c The only thing that must be supplied in order to use this c routine on your problem is to change the array dimensions c appropriately, to specify WHICH eigenvalues you want to compute c and to supply a matrix-vector product c c w <- Av c c in place of the call to AV( ) below. c c Once usage of this routine is understood, you may wish to explore c the other available options to improve convergence, to solve generalized c problems, etc. Look at the file ex-nonsym.doc in DOCUMENTS directory. c This codes implements c c\Example-1 c ... Suppose we want to solve A*x = lambda*x in regular mode, c where A is obtained from the standard central difference c discretization of the convection-diffusion operator c (Laplacian u) + rho*(du / dx) c on the unit square, with zero Dirichlet boundary condition. c c ... OP = A and B = I. c ... Assume "call av (nx,x,y)" computes y = A*x c ... Use mode 1 of DNAUPD. c c\BeginLib c c\Routines called: c dnaupd ARPACK reverse communication interface routine. c dneupd ARPACK routine that returns Ritz values and (optionally) c Ritz vectors. c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully. c daxpy Level 1 BLAS that computes y <- alpha*x+y. c dnrm2 Level 1 BLAS that computes the norm of a vector. c av Matrix vector multiplication routine that computes A*x. c tv Matrix vector multiplication routine that computes T*x, c where T is a tridiagonal matrix. It is used in routine c av. c c\Author c Richard Lehoucq c Danny Sorensen c Chao Yang c Dept. of Computational & c Applied Mathematics c Rice University c Houston, Texas c c\SCCS Information: @(#) c FILE: nsimp.F SID: 2.5 DATE OF SID: 10/17/00 RELEASE: 2 c c\Remarks c 1. None c c\EndLib c--------------------------------------------------------------------------- c c %------------------------------------------------------% c | Storage Declarations: | c | | c | The maximum dimensions for all arrays are | c | set here to accommodate a problem size of | c | N .le. MAXN | c | | c | NEV is the number of eigenvalues requested. | c | See specifications for ARPACK usage below. | c | | c | NCV is the largest number of basis vectors that will | c | be used in the Implicitly Restarted Arnoldi | c | Process. Work per major iteration is | c | proportional to N*NCV*NCV. | c | | c | You must set: | c | | c | MAXN: Maximum dimension of the A allowed. | c | MAXNEV: Maximum NEV allowed. | c | MAXNCV: Maximum NCV allowed. | c %------------------------------------------------------% c integer maxn, maxnev, maxncv, ldv parameter (maxn=2500, maxnev=12, maxncv=30, ldv=maxn) c c %--------------% c | Local Arrays | c %--------------% c integer iparam(11), ipntr(14) logical select(maxncv) Double precision & ax(maxn), d(maxncv,3), resid(maxn), & v(ldv,maxncv), workd(3*maxn), & workev(3*maxncv), & workl(3*maxncv*maxncv+6*maxncv) c c %---------------% c | Local Scalars | c %---------------% c character bmat*1, which*2 integer ido, n, nx, nev, ncv, lworkl, info, ierr, & j, ishfts, maxitr, mode1, nconv Double precision & tol, sigmar, sigmai logical first, rvec c c %------------% c | Parameters | c %------------% c Double precision & zero parameter (zero = 0.0D+0) c c %-----------------------------% c | BLAS & LAPACK routines used | c %-----------------------------% c Double precision & dlapy2, dnrm2 external dlapy2, dnrm2, daxpy c c %--------------------% c | Intrinsic function | c %--------------------% c intrinsic abs c c Storage and variables for getting matrix from disk c integer dimA, sizeA parameter (dimA = 50) parameter (sizeA = dimA*dimA) character rep*10 character field*7 character symm*19 double precision A(sizeA) c c %-----------------------% c | Executable Statements | c %-----------------------% c c %-------------------------------------------------% c | The following include statement and assignments | c | initiate trace output from the internal | c | actions of ARPACK. See debug.doc in the | c | DOCUMENTS directory for usage. Initially, the | c | most useful information will be a breakdown of | c | time spent in the various stages of computation | c | given by setting mnaupd = 1. | c %-------------------------------------------------% c include 'debug.h' ndigit = -3 logfil = 6 mnaitr = 0 mnapps = 0 mnaupd = 1 mnaup2 = 0 mneigh = 0 mneupd = 0 c c Read in A matrix from disk, Matrix Market format c open(10, FILE='testA.mtx',STATUS='OLD') call mmread(10,rep,field,symm,nrows,ncols,nnz,sizeA, * temp,temp,temp,A,temp) close(10) c c %-------------------------------------------------% c | The following sets dimensions for this problem. | c %-------------------------------------------------% c nx = dimA n = nx*nx c c %-----------------------------------------------% c | | c | Specifications for ARPACK usage are set | c | below: | c | | c | 1) NEV = 4 asks for 4 eigenvalues to be | c | computed. | c | | c | 2) NCV = 20 sets the length of the Arnoldi | c | factorization. | c | | c | 3) This is a standard problem. | c | (indicated by bmat = 'I') | c | | c | 4) Ask for the NEV eigenvalues of | c | largest magnitude. | c | (indicated by which = 'LM') | c | See documentation in DNAUPD for the | c | other options SM, LR, SR, LI, SI. | c | | c | Note: NEV and NCV must satisfy the following | c | conditions: | c | NEV <= MAXNEV | c | NEV + 2 <= NCV <= MAXNCV | c | | c %-----------------------------------------------% c nev = 10 ncv = 20 bmat = 'I' which = 'SR' c if ( n .gt. maxn ) then print *, ' ERROR with _NSIMP: N is greater than MAXN ' go to 9000 else if ( nev .gt. maxnev ) then print *, ' ERROR with _NSIMP: NEV is greater than MAXNEV ' go to 9000 else if ( ncv .gt. maxncv ) then print *, ' ERROR with _NSIMP: NCV is greater than MAXNCV ' go to 9000 end if c c %-----------------------------------------------------% c | | c | Specification of stopping rules and initial | c | conditions before calling DNAUPD | c | | c | TOL determines the stopping criterion. | c | | c | Expect | c | abs(lambdaC - lambdaT) < TOL*abs(lambdaC) | c | computed true | c | | c | If TOL .le. 0, then TOL <- macheps | c | (machine precision) is used. | c | | c | IDO is the REVERSE COMMUNICATION parameter | c | used to specify actions to be taken on return | c | from DNAUPD. (see usage below) | c | | c | It MUST initially be set to 0 before the first | c | call to DNAUPD. | c | | c | INFO on entry specifies starting vector information | c | and on return indicates error codes | c | | c | Initially, setting INFO=0 indicates that a | c | random starting vector is requested to | c | start the ARNOLDI iteration. Setting INFO to | c | a nonzero value on the initial call is used | c | if you want to specify your own starting | c | vector (This vector must be placed in RESID). | c | | c | The work array WORKL is used in DNAUPD as | c | workspace. Its dimension LWORKL is set as | c | illustrated below. | c | | c %-----------------------------------------------------% c lworkl = 3*ncv**2+6*ncv tol = zero ido = 0 info = 0 c c %---------------------------------------------------% c | Specification of Algorithm Mode: | c | | c | This program uses the exact shift strategy | c | (indicated by setting IPARAM(1) = 1). | c | IPARAM(3) specifies the maximum number of Arnoldi | c | iterations allowed. Mode 1 of DNAUPD is used | c | (IPARAM(7) = 1). All these options can be changed | c | by the user. For details see the documentation in | c | DNAUPD. | c %---------------------------------------------------% c ishfts = 1 maxitr = 30 mode1 = 1 c iparam(1) = ishfts c iparam(3) = maxitr c iparam(7) = mode1 c c %-------------------------------------------% c | M A I N L O O P (Reverse communication) | c %-------------------------------------------% c 10 continue c c %---------------------------------------------% c | Repeatedly call the routine DNAUPD and take | c | actions indicated by parameter IDO until | c | either convergence is indicated or maxitr | c | has been exceeded. | c %---------------------------------------------% c call dnaupd ( ido, bmat, n, which, nev, tol, resid, ncv, & v, ldv, iparam, ipntr, workd, workl, lworkl, & info ) c if (ido .eq. -1 .or. ido .eq. 1) then c c %-------------------------------------------% c | Perform matrix vector multiplication | c | y <--- Op*x | c | The user should supply his/her own | c | matrix vector multiplication routine here | c | that takes workd(ipntr(1)) as the input | c | vector, and return the matrix vector | c | product to workd(ipntr(2)). | c %-------------------------------------------% c call av (nx, A, workd(ipntr(1)), workd(ipntr(2))) c c %-----------------------------------------% c | L O O P B A C K to call DNAUPD again. | c %-----------------------------------------% c go to 10 c endif c c %----------------------------------------% c | Either we have convergence or there is | c | an error. | c %----------------------------------------% c if ( info .lt. 0 ) then c c %--------------------------% c | Error message, check the | c | documentation in DNAUPD. | c %--------------------------% c print *, ' ' print *, ' Error with _naupd, info = ',info print *, ' Check the documentation of _naupd' print *, ' ' c else c c %-------------------------------------------% c | No fatal errors occurred. | c | Post-Process using DNEUPD. | c | | c | Computed eigenvalues may be extracted. | c | | c | Eigenvectors may be also computed now if | c | desired. (indicated by rvec = .true.) | c | | c | The routine DNEUPD now called to do this | c | post processing (Other modes may require | c | more complicated post processing than | c | mode1,) | c | | c %-------------------------------------------% c c change to .true. to invoke bug with latest ARPACK rvec = .true. c call dneupd ( rvec, 'A', select, d, d(1,2), v, ldv, & sigmar, sigmai, workev, bmat, n, which, nev, tol, & resid, ncv, v, ldv, iparam, ipntr, workd, workl, & lworkl, ierr ) c c %------------------------------------------------% c | The real parts of the eigenvalues are returned | c | in the first column of the two dimensional | c | array D, and the IMAGINARY part are returned | c | in the second column of D. The corresponding | c | eigenvectors are returned in the first | c | NCONV (= IPARAM(5)) columns of the two | c | dimensional array V if requested. Otherwise, | c | an orthogonal basis for the invariant subspace | c | corresponding to the eigenvalues in D is | c | returned in V. | c %------------------------------------------------% c if ( ierr .ne. 0) then c c %------------------------------------% c | Error condition: | c | Check the documentation of DNEUPD. | c %------------------------------------% c print *, ' ' print *, ' Error with _neupd, info = ', ierr print *, ' Check the documentation of _neupd. ' print *, ' ' c else c first = .true. nconv = iparam(5) do 20 j=1, nconv c c %---------------------------% c | Compute the residual norm | c | | c | || A*x - lambda*x || | c | | c | for the NCONV accurately | c | computed eigenvalues and | c | eigenvectors. (IPARAM(5) | c | indicates how many are | c | accurate to the requested | c | tolerance) | c %---------------------------% c if (d(j,2) .eq. zero) then c c %--------------------% c | Ritz value is real | c %--------------------% c call av(nx, A, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) d(j,3) = d(j,3) / abs(d(j,1)) c else if (first) then c c %------------------------% c | Ritz value is complex. | c | Residual of one Ritz | c | value of the conjugate | c | pair is computed. | c %------------------------% c call av(nx, A, v(1,j), ax) call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) call daxpy(n, d(j,2), v(1,j+1), 1, ax, 1) d(j,3) = dnrm2(n, ax, 1) call av(nx, A, v(1,j+1), ax) call daxpy(n, -d(j,2), v(1,j), 1, ax, 1) call daxpy(n, -d(j,1), v(1,j+1), 1, ax, 1) d(j,3) = dlapy2( d(j,3), dnrm2(n, ax, 1) ) d(j,3) = d(j,3) / dlapy2(d(j,1),d(j,2)) d(j+1,3) = d(j,3) first = .false. else first = .true. end if c 20 continue c c %-----------------------------% c | Display computed residuals. | c %-----------------------------% c call dmout(6, nconv, 3, d, maxncv, -6, & 'Ritz values (Real, Imag) and residual residuals') end if c c %-------------------------------------------% c | Print additional convergence information. | c %-------------------------------------------% c if ( info .eq. 1) then print *, ' ' print *, ' Maximum number of iterations reached.' print *, ' ' else if ( info .eq. 3) then print *, ' ' print *, ' No shifts could be applied during implicit', & ' Arnoldi update, try increasing NCV.' print *, ' ' end if c print *, ' ' print *, ' _NSIMP ' print *, ' ====== ' print *, ' ' print *, ' Size of the matrix is ', n print *, ' The number of Ritz values requested is ', nev print *, ' The number of Arnoldi vectors generated', & ' (NCV) is ', ncv print *, ' What portion of the spectrum: ', which print *, ' The number of converged Ritz values is ', & nconv print *, ' The number of Implicit Arnoldi update', & ' iterations taken is ', iparam(3) print *, ' The number of OP*x is ', iparam(9) print *, ' The convergence criterion is ', tol print *, ' ' c end if c c %---------------------------% c | Done with program dnsimp. | c %---------------------------% c 9000 continue c end c c========================================================================== c c matrix vector subroutine for Matrix Market format c subroutine av (nx, A, v, w) integer nx double precision A(nx*nx) double precision v(nx) double precision w(nx) CALL DGEMV('N', nx, nx, 1.D0, A, nx, v, 1, 0.D0, w, 1) return end c========================================================================== arpack-ng-3.3.0/TESTS/mmio.f000066400000000000000000000710711260666001200153770ustar00rootroot00000000000000 subroutine mmread(iunit,rep,field,symm,rows,cols,nnz,nnzmax, * indx,jndx,ival,rval,cval) ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c This routine will read data from a matrix market formatted file. c The data may be either sparse coordinate format, or dense array format. c c The unit iunit must be open, and the file will be rewound on return. c c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov) c 18-Oct-96 Change in routine name to match C and Matlab routines. c 30-Oct-96 Bug fixes in mmio.f: c -looping for comment lines c -fixed non-ansi zero stringlength c -incorrect size calculation for skew-symmetric arrays c Other changes in mmio.f: c -added integer value parameter to calling sequences c -enforced proper count in size info line c -added routine to count words in string (countwd) c (Thanks to G.P.Leendetse and H.Oudshoom for their review c of the initial version and suggested fixes.) c 15-Oct-08 fixed illegal attempt of mimicking "do while" construct c by redifing limits inside loop. (lines 443-450) c (Thanks to Geraldo Veiga for his comments.) c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Arguments: c c name type in/out description c --------------------------------------------------------------- c c iunit integer in Unit identifier for the file c containing the data to be read. c Must be open prior to call. c Will be rewound on return. c c rep character*10 out Matrix Market 'representation' c indicator. On return: c c coordinate (for sparse data) c array (for dense data) c elemental (to be added) c c field character*7 out Matrix Market 'field'. On return: c c real c complex c integer c pattern c c symm character*19 out Matrix Market 'field'. On return: c c symmetric c hermitian c skew-symmetric c general c c rows integer out Number of rows in matrix. c c cols integer out Number of columns in matrix. c c nnz integer out Number of nonzero entries required to c store matrix. c c nnzmax integer in Maximum dimension of data arrays. c c indx integer(nnz)out Row indices for coordinate format. c Undefined for array format. c c jndx integer(nnz)out Column indices for coordinate format. c Undefined for array format. c c ival integer(nnz) out Integer data (if applicable, see 'field') c c rval double(nnz) out Real data (if applicable, see 'field') c c cval complex(nnz)out Complex data (if applicable, see 'field') c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Declarations: c integer ival(*) double precision rval(*) complex cval(*) double precision rpart,ipart integer indx(*) integer jndx(*) integer i, rows, cols, nnz, nnzreq, nnzmax, iunit integer count character mmhead*15 character mmtype*6 character rep*10 character field*7 character symm*19 character tmp1*1024 character tmp2*2 c c Read header line and check validity: c read (iunit,end=1000,fmt=5) tmp1 5 format(1024A) call getwd(mmhead,tmp1,1024,1,next,count) if ( count .eq. 0 ) go to 5000 call getwd(mmtype,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(rep,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(field,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(symm,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 if ( mmhead .ne. '%%MatrixMarket' ) go to 5000 c c Convert type code to lower case for easier comparisons: c call lowerc(mmtype,1,6) if ( mmtype .ne. 'matrix' ) then print *,'Invalid matrix type: ',mmtype print *,'This reader only understands type ''matrix''.' stop else call lowerc(rep,1,10) call lowerc(field,1,7) call lowerc(symm,1,19) endif c c Test input qualifiers: c if (rep .ne. 'coordinate' .and. rep .ne. 'array' ) * go to 6000 if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' .and. * field .ne. 'pattern') go to 7000 if (rep .eq. 'array' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' ) go to 8000 if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and. * symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric') * go to 9000 c c Read through comment lines, ignoring content: c read (iunit,end=2000,fmt=200) tmp2 200 format(1a) 10 continue if ( tmp2(1:1) .ne. '%' ) then go to 20 endif read (iunit,end=2000,fmt=200) tmp2 go to 10 20 continue c c Just read a non-comment. c Now, back up a line, and read for first int, and back up c again. This will set pointer to just before apparent size c info line. c Before continuing with free form input, count the number of c words on the size info line to ensure there is the right amount c of info (2 words for array matrices, 3 for coordinate matrices). c backspace (iunit) read (iunit,end=1000,fmt=5) tmp1 call countwd(tmp1,1024,1,count) if ( rep .eq. 'array' .and. count .ne. 2 ) go to 3000 if ( rep .eq. 'coordinate' .and. count .ne. 3 ) go to 3500 c c Correct number of words are present, now back up and read them. c backspace (iunit) c if ( rep .eq. 'coordinate' ) then c c Read matrix in sparse coordinate format c read (iunit,fmt=*) rows,cols,nnz c c Check to ensure adequate storage is available c if ( nnz .gt. nnzmax ) then print *,'insufficent array lengths for matrix of ',nnz, * ' nonzeros.' print *,'resize nnzmax to at least ',nnz,'. (currently ', * nnzmax,')' stop endif c c Read data according to data type (real,integer,complex, or pattern) c if ( field .eq. 'integer' ) then do 30 i=1,nnz read (iunit,fmt=*,end=4000) indx(i),jndx(i),ival(i) 30 continue elseif ( field .eq. 'real' ) then do 35 i=1,nnz read (iunit,fmt=*,end=4000) indx(i),jndx(i),rval(i) 35 continue elseif ( field .eq. 'complex' ) then do 40 i=1,nnz read (iunit,fmt=*,end=4000) indx(i),jndx(i),rpart,ipart cval(i) = cmplx(rpart,ipart) 40 continue elseif ( field .eq. 'pattern' ) then do 50 i=1,nnz read (iunit,fmt=*,end=4000) indx(i),jndx(i) 50 continue else print *,'''',field,''' data type not recognized.' stop endif rewind(iunit) return c elseif ( rep .eq. 'array' ) then c c Read matrix in dense column-oriented array format c read (iunit,fmt=*) rows,cols c c Check to ensure adequate storage is available c if ( symm .eq. 'symmetric' .or. symm .eq. 'hermitian' ) then nnzreq = (rows*cols - rows)/2 + rows nnz = nnzreq elseif ( symm .eq. 'skew-symmetric' ) then nnzreq = (rows*cols - rows)/2 nnz = nnzreq else nnzreq = rows*cols nnz = nnzreq endif if ( nnzreq .gt. nnzmax ) then print *,'insufficent array length for ',rows, ' by ', * cols,' dense ',symm,' matrix.' print *,'resize nnzmax to at least ',nnzreq,'. (currently ', * nnzmax,')' stop endif c c Read data according to data type (real,integer,complex, or pattern) c if ( field .eq. 'integer' ) then do 60 i=1,nnzreq read (iunit,fmt=*,end=4000) ival(i) 60 continue elseif ( field .eq. 'real' ) then do 65 i=1,nnzreq read (iunit,fmt=*,end=4000) rval(i) 65 continue elseif ( field .eq. 'complex' ) then do 70 i=1,nnzreq read (iunit,fmt=*,end=4000) rpart,ipart cval(i) = cmplx(rpart,ipart) 70 continue else print *,'''pattern'' data not consistant with type ''array''' stop endif rewind(iunit) return else print *,'''',rep,''' representation not recognized.' print *, 'Recognized representations:' print *, ' array' print *, ' coordinate' stop endif c c Various error conditions: c 1000 print *,'Premature end-of-file.' print *,'No lines found.' stop 2000 print *,'Premature end-of-file.' print *,'No data lines found.' stop 3000 print *,'Size info inconsistant with representation.' print *,'Array matrices need exactly 2 size descriptors.' print *, count,' were found.' stop 3500 print *,'Size info inconsistant with representation.' print *,'Coordinate matrices need exactly 3 size descriptors.' print *, count,' were found.' stop 4000 print *,'Premature end-of-file.' print *,'Check that the data file contains ',nnz, * ' lines of i,j,[val] data.' print *,'(it appears there are only ',i,' such lines.)' stop 5000 print *,'Invalid matrix header: ',tmp1 print *,'Correct header format:' print *,'%%MatrixMarket type representation field symmetry' print * print *,'Check specification and try again.' 6000 print *,'''',rep,''' representation not recognized.' print *, 'Recognized representations:' print *, ' array' print *, ' coordinate' stop 7000 print *,'''',field,''' field is not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' print *, ' pattern' stop 8000 print *,'''',field,''' arrays are not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' stop 9000 print *,'''',symm,''' symmetry is not recognized.' print *, 'Recognized symmetries:' print *, ' general' print *, ' symmetric' print *, ' hermitian' print *, ' skew-symmetric' stop cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc end cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c End of subroutine mmread cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc subroutine mminfo(iunit,rep,field,symm,rows,cols,nnz) ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c This routine will read header information from a Matrix Market c formatted file. c c The unit iunit must be open, and the file will be rewound on return. c c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov) c 18-Oct-96 Change in routine name to match C and Matlab routines. c 30-Oct-96 Bug fixes in mmio.f: c -looping for comment lines c -fixed non-ansi zero stringlength c -incorrect size calculation for skew-symmetric arrays c Other changes in mmio.f: c -added integer value parameter to calling sequences c -enforced proper count in size info line c -added routine to count words in string (countwd) c (Thanks to G.P.Leendetse and H.Oudshoom for their review c of the initial version and suggested fixes.) ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Arguments: c c name type in/out description c --------------------------------------------------------------- c c iunit integer in Unit identifier for the open file c containing the data to be read. c c rep character*10 out Matrix Market 'representation' c indicator. On return: c c coordinate (for sparse data) c array (for dense data) c elemental (to be added) c c field character*7 out Matrix Market 'field'. On return: c c real c complex c integer c pattern c c symm character*19 out Matrix Market 'field'. On return: c c symmetric c hermitian c skew-symmetric c general c c rows integer out Number of rows in matrix. c c cols integer out Number of columns in matrix. c c nnz integer out Number of nonzero entries required to store c the matrix. c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Declarations: c integer i, rows, cols, nnz, iunit integer count character mmhead*14 character mmtype*6 character rep*10 character field*7 character symm*19 character tmp1*1024 character tmp2*2 c c Read header line and check validity: c read (iunit,end=1000,fmt=5) tmp1 5 format(1024A) c c Parse words from header line: c call getwd(mmhead,tmp1,1024,1,next,count) if ( count .eq. 0 ) go to 5000 call getwd(mmtype,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(rep,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(field,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 call getwd(symm,tmp1,1024,next,next,count) if ( count .eq. 0 ) go to 5000 if ( mmhead .ne. '%%MatrixMarket' ) go to 5000 c c Convert type code to upper case for easier comparisons: c call lowerc(mmtype,1,6) if ( mmtype .ne. 'matrix' ) then print *,'Invalid matrix type: ',mmtype print *,'This reader only understands type ''matrix''.' stop else call lowerc(rep,1,10) call lowerc(field,1,7) call lowerc(symm,1,19) endif c c Test input qualifiers: c if (rep .ne. 'coordinate' .and. rep .ne. 'array' ) * go to 6000 if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' .and. * field .ne. 'pattern') go to 7000 if (rep .eq. 'array' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' ) go to 8000 if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and. * symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric') * go to 9000 c c Read through comment lines, ignoring content: c read (iunit,end=2000,fmt=200) tmp2 200 format(1a) 10 continue if ( tmp2(1:1) .ne. '%' ) then go to 20 endif read (iunit,end=2000,fmt=200) tmp2 go to 10 20 continue c c Just read a non-comment. c Now, back up a line, and read for first int, and back up c again. This will set pointer to just before apparent size c info line. c Before continuing with free form input, count the number of c words on the size info line to ensure there is the right amount c of info (2 words for array matrices, 3 for coordinate matrices). c backspace (iunit) read (iunit,end=1000,fmt=5) tmp1 call countwd(tmp1,1024,1,count) if ( rep .eq. 'array' .and. count .ne. 2 ) go to 3000 if ( rep .eq. 'coordinate' .and. count .ne. 3 ) go to 3500 c c Correct number of words are present, now back up and read them. c backspace (iunit) c if ( rep .eq. 'coordinate' ) then c c Read matrix in sparse coordinate format c read (iunit,fmt=*) rows,cols,nnz c c Rewind before returning c rewind(iunit) return c elseif ( rep .eq. 'array' ) then c c Read matrix in dense column-oriented array format c read (iunit,fmt=*) rows,cols if ( symm .eq. 'symmetric' .or. symm .eq. 'hermitian' ) then nnz = (rows*cols - rows)/2 + rows elseif ( symm .eq. 'skew-symmetric' ) then nnz = (rows*cols - rows)/2 else nnz = rows*cols endif c c Rewind before returning c rewind(iunit) return else print *,'''',rep,''' representation not recognized.' print *, 'Recognized representations:' print *, ' array' print *, ' coordinate' stop endif c c Various error conditions: c 1000 print *,'Premature end-of-file.' print *,'No lines found.' stop 2000 print *,'Premature end-of-file.' print *,'No data found.' stop 3000 print *,'Size info inconsistant with representation.' print *,'Array matrices need exactly 2 size descriptors.' print *, count,' were found.' stop 3500 print *,'Size info inconsistant with representation.' print *,'Coordinate matrices need exactly 3 size descriptors.' print *, count,' were found.' stop 5000 print *,'Invalid matrix header: ',tmp1 print *,'Correct header format:' print *,'%%MatrixMarket type representation field symmetry' print * print *,'Check specification and try again.' stop 6000 print *,'''',rep,''' representation not recognized.' print *, 'Recognized representations:' print *, ' array' print *, ' coordinate' stop 7000 print *,'''',field,''' field is not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' print *, ' pattern' stop 8000 print *,'''',field,''' arrays are not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' stop 9000 print *,'''',symm,''' symmetry is not recognized.' print *, 'Recognized symmetries:' print *, ' general' print *, ' symmetric' print *, ' hermitian' print *, ' skew-symmetric' stop cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc end cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c End of subroutine mmread cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc subroutine mmwrite(ounit,rep,field,symm,rows,cols,nnz, * indx,jndx,ival,rval,cval) ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c This routine will write data to a matrix market formatted file. c The data may be either sparse coordinate format, or dense array format. c c The unit ounit must be open. c c 20-Sept-96 Karin A. Remington, NIST ACMD (karin@cam.nist.gov) c 18-Oct-96 Change in routine name to match C and Matlab routines. c 30-Oct-96 Bug fixes in mmio.f: c -looping for comment lines c -fixed non-ansi zero stringlength c -incorrect size calculation for skew-symmetric arrays c Other changes in mmio.f: c -added integer value parameter to calling sequences c -enforced proper count in size info line c -added routine to count words in string (countwd) c (Thanks to G.P.Leendetse and H.Oudshoom for their review c of the initial version and suggested fixes.) ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Arguments: c c name type in/out description c --------------------------------------------------------------- c c ounit integer in Unit identifier for the file c to which the data will be written. c Must be open prior to call. c c rep character* in Matrix Market 'representation' c indicator. Valid inputs: c c coordinate (for sparse data) c array (for dense data) c *elemental* (to be added) c c field character* in Matrix Market 'field'. Valid inputs: c c real c complex c integer c pattern (not valid for dense arrays) c c symm character* in Matrix Market 'field'. Valid inputs: c c symmetric c hermitian c skew-symmetric c general c c rows integer in Number of rows in matrix. c c cols integer in Number of columns in matrix. c c nnz integer in Number of nonzero entries in matrix. c (rows*cols for array matrices) c c indx integer(nnz)in Row indices for coordinate format. c Undefined for array format. c c jndx integer(nnz)in Column indices for coordinate format. c Undefined for array format. c c ival integer(nnz) in Integer data (if applicable, see 'field') c c rval double(nnz) in Real data (if applicable, see 'field') c c cval complex(nnz)in Complex data (if applicable, see 'field') c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Declarations: c integer ival(*) double precision rval(*) complex cval(*) integer indx(*) integer jndx(*) integer i, rows, cols, nnz, nnzreq, ounit character*(*)rep,field,symm c c Test input qualifiers: c if (rep .ne. 'coordinate' .and. rep .ne. 'array' ) * go to 1000 if (rep .eq. 'coordinate' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' .and. * field .ne. 'pattern') go to 2000 if (rep .eq. 'array' .and. field .ne. 'integer' .and. * field .ne. 'real' .and. field .ne. 'complex' ) go to 3000 if (symm .ne. 'general' .and. symm .ne. 'symmetric' .and. * symm .ne. 'hermitian' .and. symm .ne. 'skew-symmetric') * go to 4000 c c Write header line: c write(unit=ounit,fmt=5)rep,' ',field,' ',symm 5 format('%%MatrixMarket matrix ',11A,1A,8A,1A,20A) c c Write size information: c if ( rep .eq. 'coordinate' ) then nnzreq=nnz write(unit=ounit,fmt=*) rows,cols,nnz if ( field .eq. 'integer' ) then do 10 i=1,nnzreq write(unit=ounit,fmt=*)indx(i),jndx(i),ival(i) 10 continue elseif ( field .eq. 'real' ) then do 20 i=1,nnzreq write(unit=ounit,fmt=*)indx(i),jndx(i),rval(i) 20 continue elseif ( field .eq. 'complex' ) then do 30 i=1,nnzreq write(unit=ounit,fmt=*)indx(i),jndx(i), * real(cval(i)),aimag(cval(i)) 30 continue else c field .eq. 'pattern' do 40 i=1,nnzreq write(unit=ounit,fmt=*)indx(i),jndx(i) 40 continue endif else c rep .eq. 'array' if ( symm .eq. 'general' ) then nnzreq = rows*cols elseif ( symm .eq. 'symmetric' .or. * symm .eq. 'hermitian' ) then nnzreq = (rows*cols - rows)/2 + rows else c symm .eq. 'skew-symmetric' nnzreq = (rows*cols - rows)/2 endif write(unit=ounit,fmt=*)rows,cols if ( field .eq. 'integer' ) then do 50 i=1,nnzreq write(unit=ounit,fmt=*)ival(i) 50 continue elseif ( field .eq. 'real' ) then do 60 i=1,nnzreq write(unit=ounit,fmt=*)rval(i) 60 continue else c field .eq. 'complex' do 70 i=1,nnzreq write(unit=ounit,fmt=*)real(cval(i)),aimag(cval(i)) 70 continue endif endif return c c Various errors c 1000 print *,'''',rep,''' representation not recognized.' print *, 'Recognized representations:' print *, ' array' print *, ' coordinate' stop 2000 print *,'''',field,''' field is not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' print *, ' pattern' stop 3000 print *,'''',field,''' arrays are not recognized.' print *, 'Recognized fields:' print *, ' real' print *, ' complex' print *, ' integer' stop 4000 print *,'''',symm,''' symmetry is not recognized.' print *, 'Recognized symmetries:' print *, ' general' print *, ' symmetric' print *, ' hermitian' print *, ' skew-symmetric' stop cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc end cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c End of subroutine mmwrite cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc subroutine lowerc(string,pos,len) cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c Convert uppercase letters to lowercase letters in string with c starting postion pos and length len. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc integer pos, len character*(*) string character*26 lcase, ucase save lcase,ucase data lcase/'abcdefghijklmnopqrstuvwxyz'/ data ucase/'ABCDEFGHIJKLMNOPQRSTUVWXYZ'/ do 10 i=pos,len k = index(ucase,string(i:i)) if (k.ne.0) string(i:i) = lcase(k:k) 10 continue return end subroutine getwd(word,string,slen,start,next,wlen) cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c Getwd extracts the first word from string starting c at position start. On return, next is the position c of the blank which terminates the word in string. c If the found word is longer than the allocated space c for the word in the calling program, the word will be c truncated to fit. c Count is set to the length of the word found. c c 30-Oct-96 Bug fix: fixed non-ansi zero stringlength cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc integer slen, start, next, begin, space, wlen character*(*) word character*(*) string begin = start do 5 i=start,slen space = index(string(i:slen),' ') if ( space .gt. 1) then next = i+space-1 go to 100 endif begin=begin+1 5 continue 100 continue wlen=next-begin if ( wlen .le. 0 ) then wlen = 0 word = ' ' return endif word=string(begin:begin+wlen) return end subroutine countwd(string,slen,start,count) cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c Countwd counts the number of words in string starting c at position start. On return, count is the number of words. c 30-Oct-96 Routine added cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc character*(*) string integer slen, start, next, wordlength, count character tmp2*2 count = 0 next = 1 10 call getwd(tmp2,string,1024,next,next,wordlength) if ( wordlength .gt. 0 ) then count = count + 1 go to 10 endif return end arpack-ng-3.3.0/TESTS/test-dnsimp.sh000077500000000000000000000000701260666001200170640ustar00rootroot00000000000000#!/bin/sh pwd=$(pwd) cd "$srcdir" && exec "$pwd/dnsimp" arpack-ng-3.3.0/TESTS/testA.mtx000066400000000000000000001416131260666001200161010ustar00rootroot00000000000000%%MatrixMarket matrix array real general 50 50 0.785477746971993 0.3487979039537641 0.7805146932399352 0.04639733830233506 0.3528326397346507 0.3569978249760635 0.1297350384361505 0.982246278024004 0.4157538437690493 0.4064852658401442 0.7826907311910321 0.4332040762007042 0.5762781335843088 0.6504683320851675 0.03301078951995928 0.4040116867030087 0.9589442371049525 0.5955197892084537 0.9330784472068183 0.9370408018054169 0.755739132102865 0.5389141853960157 0.824291331591074 0.01074684679419458 0.7465189612792997 0.1030347714755694 0.04841078390624876 0.1856911188169322 0.4728397095943639 0.009635624129514575 0.8581804875041081 0.473489526284177 0.1499347502480597 0.2454546456338438 0.05679114347296121 0.2052447977600489 0.4654891391892809 0.4609751781726875 0.3510560745857403 0.4410027719238406 0.3294070340782147 0.5720972666632248 0.9923532942572489 0.7178508247258696 0.3609955494943963 0.5727285310866952 0.380334616231601 0.3720832659542683 0.4242746440792126 0.743126890424134 0.3600804859802486 0.6264892525998698 0.8528696979940593 0.1200247511554488 0.1743426610234867 0.9506277973948728 0.9775014744646178 0.2520048750200072 0.2846204663380523 0.8382863222371713 0.8021007406466505 0.3699613252736327 0.3628109808983833 0.2717412803686399 0.2594693068200173 0.9943943764782905 0.04626332151900758 0.676333122761173 0.5016846476944681 0.1132880045247155 0.4613146610087643 0.7186305087313831 0.9606028069740032 0.5289001071687568 0.9354166990072734 0.9895869467181484 0.4657158742572806 0.3637964635117122 0.09033585803973088 0.8442037577127756 0.4137060639805334 0.7573584463229948 0.5540333917187943 0.4762402695189945 0.2665904634759624 0.1352774730481348 0.07770078242238931 0.8465934481018298 0.3370429676745105 0.6739938085623638 0.1044327527205435 0.5873658711723124 0.1148029215972856 0.2493453471253348 0.4141727194827263 0.7154667410554738 0.8696705805132049 0.8154279047505926 0.2324492267049706 0.3463352321030684 0.9606123640046534 0.3013127998659693 0.1541962714040133 0.7444364889732262 0.2828948192134233 0.3288394341063856 0.001331899324266028 0.5639135027069234 0.4441336664723178 0.1613629726756592 0.7034620730766737 0.5440310820917447 0.2546197210438877 0.3931108463236969 0.2446190883516498 0.5826889888498005 0.05274347285318848 0.6022926746467665 0.0399708089586055 0.862410181147088 0.3431098612841256 0.1122334668530195 0.5934265793357891 0.6300767436263487 0.7813804286218665 0.7365141289656262 0.7915971495933176 0.6487113375906534 0.9119083204186691 0.6060760940514087 0.7364455923975894 0.7132515252496476 0.6899871935121503 0.9198698714047484 0.9695459326452706 0.3289260712211756 0.0948157350606309 0.8065327242904161 0.6827348018214118 0.1732469749466258 0.4810099479577276 0.9393384962081817 0.1380723531464624 0.6596539707125604 0.1940392541687596 0.6264839774084364 0.6207350667460493 0.4409771822906031 0.6589473334358749 0.4471522149209517 0.8516043990050657 0.707325167402407 0.4285460912391532 0.6201970073796529 0.6411923102764684 0.8877501139999284 0.9936044688755724 0.7283538029708085 0.5058227768020763 0.0489289775130024 0.1082186368203727 0.8582963161297583 0.9159444859281713 0.6716598429495227 0.4623355728229777 0.9613897294569326 0.07991724267693834 0.3859134783732187 0.01643621003588813 0.5919071499917847 0.5682363063277869 0.01227069059721619 0.5898053099467179 0.3602165318875826 0.02543467078473394 0.978579761238208 0.132194080589215 0.5505765649427828 0.8634380874579264 0.6825406888197932 0.0349691968296445 0.4401978761541638 0.4398271265785039 0.7661117216746011 0.9998392859913364 0.2574659883339916 0.8858143208637792 0.04972157103389974 0.3316557703098792 0.7295536846326214 0.4987017737789714 0.5466595947977323 0.2246393613355143 0.1229806664092477 0.4852119902536941 0.8740422916897428 0.6414252507013896 0.448237264729561 0.1371437537469765 0.1411592626473303 0.9825957877078813 0.9718842592801087 0.4288925475331414 0.7560385100620807 0.5585906494926747 0.7566543940548329 0.9759200931130441 0.04187404891074498 0.3510034994566942 0.4766479626746113 0.1749353313910484 0.3559045434280724 0.8884694667358662 0.06915304918996579 0.09274743433829613 0.2058041811695166 0.6151989797735369 0.2734320505178574 0.7477853723015149 0.3057263303160654 0.7654443608285397 0.2528857313814297 0.6710159754058498 0.1319141076851283 0.9424483975171577 0.4445831830037891 0.3579953389560695 0.1698009580462535 0.4990740652970074 0.4521662003789466 0.06621598018508956 0.8878816746402023 0.9077841259013457 0.7826543285090828 0.4719435592128948 0.7961423037509666 0.8756473884552697 0.672251562170698 0.07038273569249898 0.1244719051636705 0.4253661833493746 0.7826657687271615 0.5891465452181943 0.472135906386569 0.03378847131208373 0.1800735356257248 0.9318196587890124 0.5907640092022789 0.5063355074004539 0.2184388567089357 0.9520510359400713 0.3622595138670178 0.4585467547031696 0.8308101379815688 0.7906650292938511 0.4410227332764227 0.624033793781809 0.9555082563177895 0.6634786584691315 0.2664909433643546 0.7231548402151613 0.5610778863444552 0.9729806673535957 0.300872644671042 0.4970204982873512 0.2839541084180133 0.07420800479069112 0.1113971873584092 0.07530693597058391 0.9961920276056592 0.5995976799427042 0.7889680133824533 0.8612686396119258 0.8270682662827376 0.9369237319378176 0.03585346059872863 0.1397107868285771 0.7254420808741763 0.8720941690444312 0.3741032715271484 0.2161875172375887 0.5760100991729804 0.02564675507870395 0.04350492459943456 0.9334492840456863 0.4016519282670342 0.784920768198348 0.2426285683246231 0.6085427249614176 0.8931839095044156 0.6294198612749861 0.9241468713515014 0.9958045717010496 0.1500898727081097 0.0247968997642114 0.9112640978694548 0.1479974584762698 0.08994305728914831 0.7156935991512468 0.1750144087214003 0.1597215901765089 0.4789321438336922 0.9487316515929421 0.7410701414583998 0.6723334621307215 0.07034524776921214 0.306105485335777 0.9368330555162471 0.8569370036714432 0.8908473807371433 0.5885869188376135 0.1625863275472845 0.1760451198070986 0.7475636146656869 0.9452858159764821 0.6579797890025046 0.5438319769493755 0.597653088285055 0.2346028920083675 0.8197677313852929 0.7884955332886817 0.5890596131763408 0.4362597781734968 0.5497394277698254 0.3529687059355037 0.9957911935288701 0.3649636000157559 0.9661744915175106 0.02474087295271821 0.7778391141332808 0.4401821193514919 0.6304999283010138 0.3140246962027101 0.9218152845077431 0.223324620519386 0.3744862718582102 0.308144382373381 0.03782247412293893 0.6051696745116568 0.8358643693596579 0.5882522328135681 0.363454795408988 0.1398851836195577 0.1165337215374741 0.9812174340694373 0.5416923490303707 0.08650990843852258 0.2560962277889639 0.2097750108362821 0.3146098036047049 0.9037515961022937 0.5206963071271951 0.1622360100122205 0.1436122075132696 0.06405307547809114 0.8546454586236044 0.9744567855933727 0.9290251035545817 0.4095202212744194 0.9016112200348491 0.4844972287823052 0.4696738402373906 0.16782819888636 0.08285847310239902 0.6331612550340965 0.3109789174444536 0.4663540347492581 0.2110694218127157 0.001445719644096899 0.7976112650229291 0.3680474260891505 0.01513757221000533 0.7149784664701372 0.218578762078392 0.6887172696251754 0.2460072212663873 0.2660848545886749 0.1320708237743482 0.3442103354331494 0.7543899837884479 0.8892386466346281 0.7104363766478412 0.2464750252404844 0.4513893484950648 0.9312242742848866 0.6156675802016933 0.2582899804934546 0.6311031740572448 0.6955321941690735 0.4036598780917015 0.1934818574131165 0.3070742247131825 0.6929545133882753 0.6303595654762358 0.2498239888406637 0.04342201773359355 0.5314514536148198 0.1762014479785938 0.5219020374730456 0.8712821356928252 0.6136128260846534 0.2714321214666282 0.8545396102204977 0.1574601396059017 0.2594186381299859 0.6705804806129237 0.225957392866863 0.8259665295501577 0.3240962823153496 0.4883865758261062 0.7637237533691866 0.7376755023326541 0.6360259462174113 0.2491409391354251 0.7343168277838188 0.3395051379245024 0.3027678383901801 0.1271419889831177 0.01014029872618327 0.9249287770547149 0.9100061956265441 0.3821479122189088 0.7013920658879069 0.6723419290946082 0.1276741301581854 0.2009690385939634 0.9028265435534628 0.8918363082972592 0.3776817348669247 0.250192901317445 0.6027014802313547 0.6254505454639542 0.01968288947887475 0.8197326024040279 0.5179445713187589 0.9094342441696686 0.1186249673851458 0.9461490412560633 0.9270448177172086 0.09480501121335916 0.4152573891451097 0.3228623167468689 0.8462535593737357 0.9479503196026123 0.7292205774342252 0.6838497247755004 0.6414119056438392 0.3158826005595834 0.7321467734818983 0.1576484094919425 0.7600706912283368 0.09190990317307413 0.9676539919570304 0.6089663483464548 0.8949524402754174 0.1941465307230787 0.9880579420484011 0.2413148615739501 0.2234209557685551 0.4019979417847204 0.780906365500356 0.8392120129369099 0.4094997745571338 0.4024005325797515 0.771750033223037 0.2491246863127975 0.8657410646456459 0.6821860668106868 0.9773929804085599 0.1855239055439958 0.2161827605131378 0.3129218581934915 0.7520120377257302 0.3677366068602035 0.6044560035391421 0.3834348914075437 0.5504878292599618 0.3854424217148836 0.665435033273495 0.01471416354633903 0.8131244687598854 0.3498559748292035 0.7155155252648524 0.9588938038786191 0.5074171207182671 0.6661682202678878 0.4294654343621953 0.8494985435682431 0.6542333772844336 0.5042577475921929 0.3685160595307131 0.6852494290194094 0.09920751517575654 0.04764683696675343 0.8693359149773495 0.651867365863888 0.6104587012058849 0.421945705248746 0.503707374957771 0.1641409233757976 0.0931721295240463 0.6853248645219484 0.1426712980869073 0.5287116532690262 0.003572773324275413 0.4250577909349806 0.2243409051764098 0.6599421323134866 0.5031018963796706 0.6000572398078374 0.200173658860432 0.137401018724244 0.02378902863438437 0.9395426982208841 0.695501323790041 0.5542331830091526 0.2954142891190643 0.0426317475056841 0.853760208334462 0.5966821008414195 0.01852677964293725 0.9331909618714797 0.009788324266871928 0.6409555396281559 0.7886853835491522 0.5265029442310405 0.291248417281234 0.6283285408839556 0.4254686715517636 0.5463703632725464 0.1907970833186644 0.7444888370095262 0.2128562192781711 0.1001224558771958 0.8963849862975128 0.822336975387737 0.8827837500502087 0.08812429541216493 0.7001876477408906 0.1702242237298729 0.8330442710530499 0.7280570847217779 0.7758930151359777 0.7634952514491528 0.05709946557471979 0.6098477216188559 0.8984718004483838 0.5161307245092146 0.5061715380674194 0.2556165564106579 0.9716031349585357 0.5811239224507527 0.9683864143366568 0.0414383729208978 0.1886282293621531 0.5197600590680359 0.6408539196628478 0.3407313225253646 0.6483298192076838 0.3554379655462507 0.8504300240413766 0.5428046812412212 0.6730800874607602 0.2565725793133774 0.1213382767079354 0.04060644586034068 0.8879431330894764 0.7531873158317328 0.8020791850262654 0.441405626647267 0.07517258571622043 0.1542296972876935 0.2472441483940219 0.0792259868541022 0.8531595631341649 0.1571768552907903 0.616662683688958 0.5284499444589416 0.1912198233556319 0.7597507602273893 0.6149984254928762 0.1520636067770824 0.4546374468581563 0.6820975998089609 0.2812591215759094 0.6248631208145372 0.9417301226014179 0.5668033360474686 0.6931155991051783 0.9785864110343221 0.8991173786750881 0.6484798960153297 0.9829208149449612 0.1638149681798106 0.5097868572275749 0.6273484296561036 0.8000009063332891 0.417769086107256 0.05483443189378079 0.5191441936509564 0.1345321356883087 0.3669744346450395 0.6966208874034296 0.129583524717075 0.7858495299874493 0.05030897359635167 0.8156155197006915 0.8669388624593534 0.1968964536536247 0.6073938011267771 0.9966797518862025 0.04237432746008252 0.1388230031294067 0.2229539740912246 0.5830104779642798 0.6711064868556157 0.7231959851182224 0.5044385129861295 0.6446302628311489 0.03636934067604214 0.1938518253349607 0.7495457121028239 0.3081783758448918 0.7490521518246954 0.85203732135201 0.09935547638279607 0.597778198787964 0.7206022557643235 0.5687138321154716 0.2351100910853098 0.910636226408683 0.9506197570954015 0.5163152948198082 0.7070881302571722 0.7987951929403031 0.1996893666527755 0.1068405154497045 0.6185748433158113 0.02222394078230217 0.03756204368831895 0.1153641215880208 0.8186972404462725 0.3768992258031192 0.2291563121361598 0.3681399130368996 0.1745404238713363 0.7747796388327376 0.330030614354014 0.3157801399284597 0.7245869006264816 0.5849549834420218 0.7777555242671685 0.3595763876506322 0.1847330019164792 0.5736891081286625 0.4830945845647806 0.4216269404540742 0.3173251923814021 0.9725715071931813 0.2582226408369922 0.5670998996464329 0.3520669047409829 0.312029608919655 0.009397602757391432 0.668127492035812 0.8856876804971914 0.4213177264716675 0.8585800527346572 0.9479924916927481 0.3761067747970577 0.2032932484898388 0.1791694952414008 0.3062940833412099 0.8503119356661379 0.5256025310447409 0.828442251880212 0.1068764588739141 0.6171420317004981 0.5668265185664312 0.2609361569069434 0.002308110432938437 0.2872550628798151 0.8212700824567727 0.8951154046804658 0.9958079096062296 0.008438401807033813 0.732843238440102 0.08461726794253233 0.633348568099204 0.80508642560858 0.8299648864350688 0.5672214497239391 0.2600433904930519 0.7845320494016645 0.1692053340210961 0.2742583451752331 0.004903194288562784 0.3975612405280391 0.02655155323080127 0.8546990498098754 0.2048916891633613 0.8603505810976838 0.05612470880554887 0.2235117723663907 0.04528051780839293 0.7509917731126146 0.6980563799302092 0.9187878891211375 0.9089226043321582 0.8055238565445589 0.9996774453746491 0.8007662757545447 0.3229153326441299 0.02514458414445353 0.7328234712837909 0.4727867045481889 0.3925884021650015 0.8600140278133452 0.05746164912061491 0.384545138525541 0.1418404203668561 0.04568139777501767 0.6979947329621027 0.9135115020681923 0.3835456322906093 0.2431108172993578 0.9070977326477642 0.7020179128680837 0.8956378868936629 0.9479735592426914 0.9366919584324206 0.9967866310119839 0.3969424719019249 0.6599364493759738 0.8229502979494715 0.6223667300062823 0.7005063181449608 0.4895151047139465 0.5088168012407174 0.7797132955598631 0.04048577616286009 0.9010074025661139 0.7320457211210215 0.6157830684792364 0.7551880444699675 0.2844671855941731 0.2062491145769358 0.6521862129091853 0.9281199379807344 0.8045735148499104 0.3504360631022279 0.2701884059955971 0.7446177131237434 0.72299211004354 0.856720355874117 0.9188193236436777 0.2690083691650179 0.6881517793620033 0.6179970516901144 0.07155347293942749 0.1883982349888309 0.3355694688608594 0.3110458209591368 0.4202040179605758 0.0877387990616133 0.5598684829070103 0.6676252498623747 0.1153017136391573 0.3156603891989895 0.9807963423973177 0.8858695377113054 0.02275832942749123 0.8632855052413426 0.2449936208834124 0.4336017292379604 0.1353762016633067 0.2155999982318065 0.7747289151080012 0.0871862609352515 0.4003778253303322 0.5901109675535792 0.1965235690729467 0.6968124642448635 0.5929693149266995 0.4641899757262669 0.2411549478594502 0.4127704545038754 0.770494470747454 0.03533889164463344 0.6075502991334615 0.07947364889801101 0.4153764550439991 0.9854775762096046 0.8426484352769673 0.05240260210805847 0.7275179108311104 0.1149580297455479 0.4853809615892408 0.8685943678229374 0.01670387911369708 0.8189083780376529 0.7838736724098379 0.1937077328774883 0.9128442913151924 0.6836899416610769 0.8883935085276821 0.7128697043986415 0.4848920215417473 0.8332180426601535 0.09074642077306749 0.02549175650536506 0.335727870856154 0.4869226263333755 0.2253628272943481 0.5547087994895158 0.6811483927579534 0.8349432084199989 0.8958728132229383 0.4375979183285483 0.3996552888503655 0.4401199541345421 0.309626357593902 0.4469533720366108 0.9643901232477963 0.4623482323420648 0.4959920123859639 0.02153989279020663 0.1922851314665226 0.8981342605295961 0.3892922234206508 0.1020461540761098 0.3496985816779994 0.178546091108624 0.2490910623761474 0.6409844498846424 0.9757541601664016 0.9206638516873854 0.05380692850017921 0.9030846790110441 0.189999378694629 0.9926151977241786 0.3264995955911637 0.2275434957740902 0.943710729255865 0.8108468741367665 0.9244441600094481 0.718502000394367 0.8792565612572231 0.8650617674700564 0.3574250884479105 0.1362764683506361 0.8057804093275702 0.6811248466872695 0.4313871163731831 0.9471154190194666 0.9511727369975825 0.03208060731819962 0.2761667599324792 0.06775301313280913 0.8269493017238748 0.3963234452332561 0.5811767116122842 0.3435337799921883 0.9712097435824162 0.6034058056474978 0.6676411499628827 0.8633251611483932 0.4200870484241666 0.07341100220830876 0.8713970581693321 0.6946542435009362 0.8414246894261694 0.6762458345921877 0.7014017087337732 0.8954172171920597 0.5874139298251868 0.3251953625892174 0.9948506456792521 0.2075384266377166 0.286252616218108 0.8331083386053986 0.7702477474361495 0.2005791077201452 0.7647662965714126 0.6159233927148443 0.9642674159837193 0.503691258942202 0.4787018227879879 0.585696853852641 0.9795917261330512 0.3490990886704107 0.2610027568737846 0.5899424153658227 0.745384843673345 0.08198390427228663 0.3749558388033744 0.08700844434196431 0.3181514054810053 0.4532299455774073 0.1610809052464525 0.05986814869606805 0.4448652178130936 0.2852737675649195 0.1991782232491761 0.5098118955233614 0.01947843300731467 0.8301025950875111 0.2003855631700716 0.4265632262848765 0.7330884934167657 0.526796772931903 0.2692985112669554 0.7678352277503803 0.9544124738411768 0.117687371272035 0.02488822009103842 0.4220401145551942 0.06438396044610384 0.1256026558549721 0.09241775384059359 0.2326892734806901 0.2111930611634079 0.6098109805009314 0.3945270527075339 0.7266983918859443 0.9612981538496442 0.7502172043406883 0.07873977287961509 0.8679530511180489 0.3627708638712371 0.7970071271924942 0.7863871879017024 0.3313547476001703 0.9499914553181076 0.8284896434884577 0.6291297470050068 0.2956236319300697 0.6170045241840419 0.9885034306411764 0.3440088920612865 0.2396446662476179 0.0003971059067402471 0.9092898522997359 0.6275404572535281 0.7862292982802862 0.7487163360037624 0.6168976342636073 0.1834015811969786 0.8435932470703686 0.7159929394496765 0.6518013355770008 0.6128070715928453 0.8737861372262379 0.7926772718219981 0.7244249759676695 0.4091544292629353 0.9976534022974836 0.6238085036155495 0.3531652535856838 0.1827231412043262 0.3209043513382621 0.2556067664510513 0.9410847472911361 0.8929066755602225 0.9880521079603376 0.9524719750638411 0.8742069176380901 0.1622435007327453 0.146688413160472 0.6498031003682845 0.7900859411420516 0.07230160920739637 0.2445194403682387 0.01070715205155892 0.232541408581099 0.2548548790028199 0.9121879618595873 0.367546572759846 0.0380340235252129 0.6508323165877404 0.8163668635963278 0.08375040803342759 0.01148104737944577 0.3656153223198011 0.4127654421939717 0.4160209899580742 0.4633760149747584 0.4660065125496495 0.5481585323512327 0.5326909217871023 0.5076925540742117 0.7810913280219699 0.2899651479814135 0.5505018812451309 0.5746653306234409 0.2038915081095624 0.5552369724125421 0.2141160238951959 0.5491567220385508 0.06976982991884895 0.8604475144821226 0.2083827073215646 0.238632095670492 0.3805852152786106 0.2873663917866944 0.7505231294217088 0.3189389712503545 0.1073696753369522 0.8061358683365647 0.2520584544709007 0.5039048520554241 0.03985083879109019 0.6241937542114872 0.3874416076885199 0.3082738496857479 0.3320499623809993 0.9315932463763674 0.4679895603100958 7.099319345438282e-05 0.725780504048086 0.3994829192730686 0.02292363397336383 0.6377423890706582 0.439352012713857 0.5917691363808901 0.6179846103570156 0.4540966724851869 0.04908527589659761 0.7196941727447486 0.7400928623847778 0.4047987945955767 0.05141252539400964 0.948004653343517 0.8773868502354092 0.8276499476889687 0.448636593326791 0.8844747141946155 0.8537183373590775 0.6477367441150418 0.5067832670556288 0.07602290854549865 0.3624068845001056 0.2310911558051516 0.8601805037239481 0.6343900558370829 0.7314571147776474 0.1563552833732814 0.9496469379126524 0.4004229537728619 0.6113866753517463 0.7984892328696712 0.6863698195202363 4.834455750957201e-05 0.502657654353642 0.9856199957539303 0.007003720947192149 0.04092932437737173 0.1034229113351951 0.6034065583567469 0.04619028632623601 0.4218719448215087 0.3558631032453929 0.6976704570571679 0.3629777257146221 0.3245550476300417 0.6774757431538212 0.5832523698543565 0.2404547972654699 0.3748665663321581 0.2047346127014699 0.2586420846776649 0.8473144924919164 0.4270409423799212 0.6569829630057124 0.5312717480393021 0.9370190407450271 0.3334224200940459 0.3609118322538046 0.746493540455523 0.8639294687684046 0.02205376993444275 0.8495239270972266 0.8076254271844439 0.5427829454587535 0.4337830747302812 0.6024369191190526 0.3351052030338844 0.7781072047494094 0.0967197534128158 0.451954974000803 0.7619490654278906 0.6258332332285546 0.001491523255652272 0.01717240515075213 0.4568540721689267 0.2215640563953248 0.3714206858025393 0.4412321642580441 0.06068954702100038 0.3640423741371652 0.3768690740109791 0.301240237258343 0.9183891801482551 0.4773506757715675 0.1803924380296581 0.2970376394627258 0.8292994736543202 0.6181239929042461 0.6635995415112846 0.6162034118163047 0.2612667243781196 0.8724987166501006 0.005368127403688749 0.3652552918622246 0.5919718384003337 0.9248390593218262 0.4580048975877193 0.4242082242977333 0.6549616120639719 0.7642363084139678 0.3796435664138894 0.4540689670682517 0.6438020122938055 0.7351545263380519 0.633821562872391 0.782944271864228 0.03448701932094589 0.1008623391586755 0.04174077875812854 0.160518423407093 0.8350029471009827 0.5594340824616484 0.1720216998258309 0.9387990091180241 0.542159328902428 0.8302578561362792 0.3174437703332581 0.2327393564501141 0.7019938124953298 0.5197836480594014 0.2861462915821057 0.0276729267053365 0.1528029022659121 0.7839226097109037 0.5187518897952131 0.416822862672221 0.1085475569845107 0.6314276750904005 0.126733568056866 0.5806436635133652 0.1845003755459412 0.4949110902032333 0.3354406183161724 0.2068487698258999 0.105165521104586 0.1536325179688556 0.8733295499475763 0.7243714983347331 0.003584176016125706 0.8104152380120612 0.245622407967823 0.885936548815393 0.8392806494752019 0.3555673851890813 0.315247116832202 0.1541863083391155 0.3884232296043179 0.3054398481989467 0.82117581307302 0.279882346584207 0.8514539477602941 0.1952851559644642 0.3550024667941819 0.3459755810988887 0.585631351305979 0.4562507954067759 0.03844871163837227 0.3800155943468968 0.5464870450062875 0.06825806662535239 0.2132264650053793 0.7718975671071883 0.6303793693353407 0.808721360720695 0.02149000823209823 0.01175688788807794 0.3987966651926876 0.2096956748344578 0.5879147401777179 0.8227218950863271 0.7490759823584625 0.929144914732334 0.5245455343216855 0.5386454166341963 0.6672944993806594 0.8712611967415711 0.1813249291815934 0.699106624590959 0.1889102032619238 0.1998162124246845 0.7709659491067911 0.5298961882052664 0.004714637195271765 0.9553610500720577 0.8772790004858393 0.8723088963835226 0.4940252349035892 0.5311016926928747 0.0322607179908051 0.7501567083195859 0.7583520129192493 0.5835627390061723 0.3701170082661117 0.4919999375109856 0.5271824580938407 0.4487244653756858 0.1424009051482739 0.6527437323294034 0.6746702883821366 0.7497627748917182 0.3059258561245995 0.8043475921286082 0.2999667985320552 0.2740866750323177 0.2704849820626636 0.7634909292790785 0.3185752154417696 0.3570044482734788 0.675481877125386 0.03353822505807458 0.1500225440578283 0.4215501220956385 0.2128941447897994 0.7600721245385718 0.6433061365554781 0.8396467139452928 0.2077957647723677 0.4383475927277096 0.7321197516417176 0.1047517185833388 0.4445647141573581 0.490552705674478 0.6944263532843418 0.9308079854818532 0.1551507753707975 0.05268122066816694 0.6086764530409728 0.2429407845481393 0.5583021964316072 0.6785006744322112 0.4665047685235638 0.658405065829952 0.8083493389239484 0.8564392355170491 0.7108779140245594 0.2633336157624828 0.2961072401244553 0.1858452494209637 0.5993767065699106 0.7782974421192767 0.09576622809206847 0.4099764488429094 0.6312457112010281 0.7653133648911961 0.515606699960211 0.04678935328563483 0.440639621831668 0.7812690838286037 0.9911459739161296 0.8492790031140809 0.05998630544276218 0.7667251981437075 0.7249065625694016 0.7546829077682189 0.2014314571693834 0.323838572852246 0.5970788423663675 0.9771135628945475 0.4514283397368585 0.4963054028398532 0.9716561385393364 0.7630045921004902 0.9797653333483775 0.20283133878472 0.03166861326167403 0.1581480286952355 0.7197034018849273 0.7772823617179596 0.6449577783675171 0.3380646585783239 0.6546523281219516 0.0456563493426857 0.8674847800881136 0.1029617494881166 0.9469693357004212 0.379497748848172 0.1345208960036298 0.312879832834512 0.8986840911360741 0.7807903970820254 0.1930413238649759 0.1739408279320189 0.893316219824227 0.7707645075743599 0.792116942050586 0.2135578525120772 0.1933726762091043 0.6467390825720987 0.1112869369577927 0.5059125207258039 0.6849215724339455 0.1570275682106105 0.3733746363000563 0.808372197161161 0.9093219312432421 0.1606895364840794 0.7379478820768828 0.5556956333212771 0.1878565968914672 0.6900143540527558 0.2998163131210611 0.6322680775669917 0.2357835014342674 0.4893431008361042 0.7582642166423046 0.6202074195843946 0.2477752804337469 0.6532079176795309 0.330785884081767 0.1192031611451035 0.6568562030968705 0.9473198884988218 0.8411543373575909 0.1463880717783439 0.687492784344319 0.6642130838728434 0.5104891837342258 0.4347218932056857 0.3835882638111207 0.8422942344656256 0.2508350181598343 0.291479801013163 0.5609688492709797 0.6266636903357052 0.4497194561502447 0.8644253224921107 0.9539571195922825 0.8165273418664679 0.7200631120940203 0.1220418066544595 0.08295422783201245 0.8391233359899599 0.350551199871815 0.9056369578551801 0.5778913994332658 0.05108653255361029 0.2156540740248768 0.1466845654599992 0.4163013408684876 0.8775582914885607 0.09295870566823849 0.929844942371153 0.9358377175184789 0.2653579348753746 0.03567886971029466 0.4664672183794293 0.584379997191826 0.7267427938994847 0.3334943690987374 0.0636822667271657 0.8916374977505059 0.8289625823503145 0.3729495826401348 0.76546316699376 0.4374009610660129 0.5182717138717996 0.5601889269064096 0.2455058815656616 0.1283052887658608 0.6104832892269054 0.6135677069786908 0.2349313039830699 0.8576099510301763 0.1153046731208617 0.8825150168947148 0.3889091105363364 0.2998224380212881 0.7529141431174664 0.2651695014510056 0.5255483245397433 0.2292347177205935 0.05638555118628963 0.8277810519354888 0.1158141136934723 0.5419230010306129 0.6246839658097595 0.0003758221893939151 0.1636151201806123 0.009516564582797704 0.7530014547485532 0.7037097547081718 0.3563410607801362 0.6704121147543829 0.09099505423899557 0.822654990430608 0.4232199741672384 0.1015881886513316 0.09758935582897554 0.106357329408205 0.6186988764147504 0.2009873519296198 0.4231980358035324 0.8090221535471258 0.3289164724718036 0.2733498264353648 0.8188288111996195 0.2064663927600562 0.6545668472417844 0.5760130779369724 0.5637127671125171 0.3146774861323062 0.145663820743122 0.1302168471104906 0.8426667069952698 0.4746116895568181 0.2316973493627692 0.7810420524673425 0.682424363146733 0.1612185648578367 0.1411937164850225 0.6687428305148433 0.6587328847758418 0.6438059367000052 0.1867879628371164 0.822098464780699 0.6137460751304099 0.9322219893430503 0.6614161590597856 0.2492031648627455 0.0466922013939649 0.03714053702677689 0.7182692437787263 0.2434180984491574 0.1456763168318614 0.04395515177802145 0.8088304531108501 0.8407237481089014 0.2295170301368117 0.7478390463100749 0.2819469376488415 0.3382515133079037 0.329206178196116 0.06663440526041897 0.07715345338561841 0.4948316295525573 0.376096669400761 0.4165866487819505 0.6196851777911678 0.6635295287371097 0.6355091145735927 0.340201638270653 0.7447552427861331 0.6955056002586417 0.5865770460551188 0.8827422705066625 0.9572091918107977 0.8600791672765772 0.3203623442153978 0.663587983731134 0.9056326469920711 0.6854112064039103 0.9991247584365847 0.4993940317059458 0.2728997171042178 0.6934103342318307 0.9950125284800352 0.2103776072150774 0.4157307331727811 0.162007507128176 0.2497219771078316 0.3937076822577935 0.3401666606419359 0.9285248836676876 0.4527238537431563 0.5265665766525548 0.501154125125536 0.810326381468528 0.804838200476692 0.1178208323109059 0.6183502289206068 0.7727275226556869 0.2848384548598178 0.269120237835473 0.4661162532708516 0.3712503248353668 0.4792406667886745 0.438207686734609 0.2552261958636121 0.1411376436401548 0.2661719595391222 0.3484837222058765 0.2525219650158795 0.01771802843293302 0.4507474890824889 0.9045816956523666 0.6570649843686319 0.1434323809846046 0.2584968365853021 0.7912647156990554 0.7273798901788984 0.8231185254316261 0.9363027725223539 0.1911715920084949 0.5269436607084196 0.2806099606082405 0.4083874267944586 0.2398529075455589 0.3575555817756102 0.1643209913064337 0.002529694477878874 0.4066580273188295 0.2796176688333473 0.1772755202620809 0.5856579770625748 0.7215181888323551 0.7212609147088103 0.5085861196357225 0.3259258294188844 0.4548378972555756 0.2968805983357771 0.683026854068294 0.924728143195075 0.2917456526722308 0.4759942350699736 0.3915443411108871 0.3188958843098935 0.4001858271215152 0.8775925398524255 0.953160377075742 0.004383438254457861 0.6014281395920986 0.7855776162110845 0.638506626625535 0.1170147906110954 0.7105127640545864 0.09774973858131786 0.5847656084539119 0.847564771084339 0.2307253695522218 0.1959879126661013 0.03782815753379265 0.8275467009741005 0.02826167377201394 0.3672386110452862 0.1748114663644544 0.5040730091568748 0.4959861980024814 0.8648814337000932 0.5711395831148516 0.1710155814627483 0.908353001332888 0.6636377269472585 0.5026889918923206 0.822084970197406 0.2876968378562964 0.8809650972655474 0.5314381385927962 0.09259364379360935 0.483544266284841 0.3217971523537261 0.5430806465734219 0.9567038750605196 0.3675241776002314 0.0264606839837801 0.7395105386133489 0.3248849680766279 0.6652865344284973 0.4978462949187131 0.8576851725762095 0.7486319656703316 0.397915820333789 0.5141143552584124 0.583756327905349 0.508243785545476 0.7338708097051049 0.7285900667380094 0.1941297362134017 0.4548926820793441 0.5186163053312298 0.1490857610670967 0.7819399415124049 0.1654329795363289 0.4952239610952458 0.259175029738592 0.6217587369746963 0.4571117744922188 0.2554557911182781 0.534400622572249 0.0916214964714942 0.5615329843565661 0.8521998769242128 0.7274906027740951 0.538697511160083 0.6716170759046064 0.8606825174849109 0.5519277130187896 0.9106831152828662 0.556749508305831 0.8583378261592052 0.4527628055743045 0.1606159062978054 0.2372150937945338 0.6117433752740724 0.4337217066993081 0.6071553148947922 0.2366558351357411 0.9335249339773627 0.7034089547854145 0.6756352577441201 0.3936358143251755 0.647503736778851 0.4492551505341909 0.9899717968300691 0.09361481278584982 0.4683740521685751 0.6936822309514781 0.9418181990364669 0.6315116588193715 0.6171159871805773 0.6435289018067313 0.1515327368058428 0.2446682262409852 0.550142288677071 0.2413076178884336 0.504063842083072 0.8012518379799675 0.6635150382125796 0.03677336451486346 0.2080297701871255 0.4031231509650309 0.9182382266179694 0.6079913868244774 0.2182999747675104 0.3489155003696005 0.267919380367911 0.3853859275473615 0.8782751137419897 0.5550247762374826 0.3249080661048463 0.6485357418472696 0.6104036193905655 0.08896262914304942 0.3668054873725067 0.9399524249625995 0.9228135125663498 0.2608572885418904 0.2645732915529539 0.7803307972048107 0.4019077916097313 0.8864559166254603 0.4521870639765907 0.4969885267327371 0.3729618660688859 0.3817095419085867 0.4580856509131209 0.7177849457649941 0.7299512684954235 0.3361320631624437 0.4642979460372829 0.3777057126165045 0.06394982480760314 0.9827019537674155 0.5962931821893948 0.4501368340000427 0.9720105885974949 0.6886543936772321 0.4879833687365164 0.3573464608417309 0.4314879451813104 0.2061947707047214 0.544849909479693 0.957502087527355 0.1870051696688149 0.7702047953380905 0.8373805010443406 0.9083137403555017 0.6306630706764909 0.5935944489250058 0.772602644287646 0.273068648621246 0.008237615043091839 0.2684188046996536 0.5338546391936502 0.2251411314700431 0.9124910119183312 0.1127385410328676 0.2663420432107302 0.4797960675956973 0.6609343229049219 0.8359470913117386 0.6347127303056589 0.8068406169449454 0.5724203364097281 0.4917113069131129 0.8015136673170312 0.4410514004968902 0.04886972718564164 0.9874602909057569 0.7492494783451867 0.5786447718377037 0.3341665882720505 0.5933519929178346 0.9016442919835091 0.8429451403179621 0.8684161339212322 0.1036371983984848 0.7873106094963864 0.4059608946523245 0.3069668456809448 0.02652032457650355 0.7104558756456958 0.843627569565131 0.04988780528223968 0.2456314030551109 0.9501568138056644 0.1100803841005638 0.9579749882722481 0.3453860336573168 0.8804481961571243 0.276029507490185 0.714448536660363 0.04971574474905371 0.107253562155779 0.8589907535298285 0.4242794681117714 0.5625256850056726 0.7327245943047813 0.9608829824610809 0.05913498388986971 0.1195660880149612 0.1308001516365505 0.8027205155165122 0.1601708571685636 0.525530254482209 0.7085921529173865 0.9903962005245053 0.610435169301708 0.2915822973187088 0.5508801636006813 0.5407105899912373 0.9005162708607162 0.07092864553697709 0.9837516060325393 0.9056940050639519 0.9389926070526617 0.6718603982545037 0.7265535208169442 0.0933698254443055 0.1354734015956748 0.8106430816074579 0.8452925958076646 0.1029718616276447 0.7558966611123731 0.3211737537593129 0.2382375670573051 0.8395999288988436 0.4214440948097979 0.6599587717680374 0.0357786992124387 0.7408030629544039 0.9975665866873257 0.3841472763912928 0.5292566409536741 0.7841642484111793 0.1622008024146887 0.9014195152987644 0.3102880354659415 0.6793093142257626 0.4591853794841392 0.6641840880605209 0.6828983170592361 0.2423286846882906 0.5437299650789259 0.1642296324342992 0.9065886607123872 0.5727220180425645 0.8452807889795116 0.9757021898067603 0.7963676855366463 0.5541240349234611 0.8731062874194454 0.2675530206890216 0.9410650048908729 0.9902633996160738 0.9173703861819479 0.03720207222203964 0.585980306873088 0.4210069757396099 0.04552947824773679 0.9252143099375978 0.7513460745875381 0.06039859244898627 0.7221340353316433 0.2863320028626405 0.9644735721057532 0.1493308817207637 0.5972034228159512 0.4651686965233579 0.4113363793156002 0.880488962719551 0.2248881876192546 0.5429623138802556 0.9476024643853722 0.6533406662893882 0.03409708326709815 0.3888555956517826 0.8739194227433489 0.3883120052345878 0.7469069210920392 0.7411060147495505 0.2297779473787719 0.9238020351193297 0.1720405432598824 0.8302527202181416 0.4108445096714834 0.7703368371497962 0.3400218830229882 0.89133524160372 0.8554264299700676 0.1319030676290006 0.6823661705663632 0.1495795268947909 0.4103679594088759 0.549947684939901 0.5518026588008819 0.7729981529023365 0.7407500887878584 0.9076753726373387 0.463715278605034 0.4008031571785572 0.94390109594086 0.09561478482071539 0.5587475596808567 0.3173953170120756 0.9447706510959202 0.618901958552541 0.4643858491800936 0.8790315351843209 0.7326852066642277 0.5892154311003451 0.1006443569792121 0.02187828055803398 0.08429697467758346 0.455152772646203 0.1883186345854497 0.07512579075822712 0.3290667104090407 0.227286979231096 0.3371710268882941 0.5524473740531782 0.9683113444471438 0.2272296837480325 0.4001456655973323 0.9907714531844382 0.4620185041248831 0.9845304523123836 0.4984403195875649 0.9880039096795565 0.5380994022812072 0.1328964933929179 0.3392031981587114 0.7290083161041685 0.4156438777036031 0.9247214317594548 0.07029164643746133 0.3793955628776755 0.5651590175733986 0.7565917862341232 0.7336655623419102 0.3812448957453333 0.9046564148882535 0.1930206576469395 0.890348095003441 0.2581756950794387 0.4136571297761859 0.003279341921906376 0.5458363342462074 0.3450070711007081 0.645588023619165 0.9321854818646257 0.587708283878026 0.2606030116912819 0.8999458527288274 0.01724623569096306 0.2279211373480438 0.7168581927040588 0.09962785372575234 0.7170175218036562 0.239580553677171 0.4128389087974799 0.2894398680546381 0.1516182588032814 0.3098016405349268 0.6334393020407166 0.0225924003937511 0.6241597991633951 0.2001888220806741 0.3970564042577788 0.4658305674043748 0.7983575444901186 0.2210043574434539 0.3823859561792219 0.9067874357260439 0.1238760764205172 0.04505731714950123 0.6896037939199376 0.2981209403072959 0.9965603320468314 0.1839315335947156 0.5551467463756341 0.5912984665067248 0.4990368060573562 0.4625596909469145 0.1527691149526219 0.2585588267018007 0.722380433394533 0.9963474143400639 0.555310311717323 0.6436788167270254 0.6808067150605602 0.9528096155865931 0.366399040866368 0.4692217889010913 0.1285397079243911 0.07980670213439545 0.5440081248219508 0.6723069580592883 0.8435069479919347 0.5983247521188737 0.06240111773359736 0.7376456137915793 0.1535854494742722 0.08510737131666235 0.04900699038614942 0.08040319634877813 0.2132904975354085 0.3885382750650893 0.2879823804891476 0.149711341131578 0.6338170036276467 0.1136909175028815 0.7344814280504979 0.8900224066623255 0.4429103024948694 0.4080863910506083 0.4138534977830822 0.8787018888665857 0.5272162521030758 0.1277437970543398 0.2115361274021211 0.1682475886746375 0.3547241074161448 0.3645586859516743 0.5516767534499161 0.1313418680595633 0.7103877272769868 0.3549878091845877 0.6470802080237382 0.4252830218048486 0.7573350173556445 0.242964184989073 0.1884441963376879 0.152735920449503 0.9912138122536411 0.9747191639555511 0.9221012006299496 0.4513026900841971 0.2018011071569559 0.3755671620412094 0.7431663128128615 0.9011007821374826 0.8604532939481959 0.9732889792898411 0.1515051392944925 0.1231577170247805 0.1938042495344156 0.2576290884056766 0.7281770932543058 0.2233662299354708 0.5970421867919924 0.1740885607824549 0.5752213207739252 0.4589827786960482 0.8829379726213226 0.006501989511032313 0.3674111613507309 0.1627369210179049 0.07629164837894686 0.9011506256347845 0.4278916184425381 0.5464766480411437 0.08703734802115193 0.5888957426324904 0.4078853370269363 0.6125779380187373 0.04034667611491349 0.04796805989424602 0.4574224643019429 0.8195271555865545 0.6988519853845492 0.5499447786681219 0.2009257036945957 0.6379872347197878 0.04532951009823127 0.720745666531769 0.4243044604981899 0.5157910609573652 0.91128073571204 0.749633768749228 0.9620748856691238 0.7573750368828713 0.4380880292722591 0.4554971759546693 0.5115828492131747 0.2336100941540931 0.4396866910270356 0.1442177885988739 0.5233882393745927 0.4037952356791581 0.05496364571117429 0.3643221764090653 0.09857597627000225 0.6099688493956323 0.2234008363868244 0.5806664147443227 0.3305101471124651 0.7464947194121648 0.7816067588025728 0.1191345263088943 0.4309887387817847 0.1453443234602514 0.09950881635531528 0.5136754513992725 0.1850545269351187 0.7252774066361717 0.03860883695316963 0.1752468586988707 0.8486341447647672 0.8299088350679383 0.2039615883228973 0.487527623521674 0.53543582114243 0.195502353530067 0.9141867671125131 0.2827732453397999 0.9510484049697426 0.6831683288993847 0.6179100932285354 0.5487318386700291 0.7779540956688812 0.2331930599595876 0.1165761976026892 0.3534281644941153 0.09962006625810271 0.3808369455539417 0.9779930182547943 0.6141110769144189 0.5759224942521924 0.4497125130176507 0.4457740797200458 0.4074422940412931 0.8985862404382988 0.4163415492366074 0.6801558147747342 0.03595588493427715 0.1780712709274711 0.09390881730226441 0.1251961972191801 0.1885289689399452 0.4654407735780366 0.1717734025725587 0.5210537442009584 0.6752911763542996 0.8688897205303052 0.7569369347440458 0.9842317524892046 0.2198400234887553 0.1729985576702801 0.9227279677718779 0.8989372598606983 0.3771974418426111 0.1371985611917274 0.1422537347907288 0.006771806362500077 0.8079297245860473 0.8248055369131398 0.9149561743850259 0.3489427142543103 0.4566375067602169 0.6456146340413252 0.6735041746419594 0.9759072204720871 0.6133586650776676 0.9277498563073998 0.9281719119181705 0.9977177938006829 0.2682936175554479 0.9461441383071844 0.1121276488405524 0.8699643510346226 0.1095112076083331 0.8982984497489168 0.6351931461255053 0.600993799383576 0.4684217342589907 0.5139049878682951 0.5447730904035982 0.6902472899025476 0.5630294749734774 0.2038726556122153 0.3751768438010991 0.6308558703217668 0.5151615182339797 0.1288018601899773 0.8298101219322016 0.839440967003994 0.3234764871651495 0.1583903614450823 0.8571778049459723 0.3174481397804656 0.2696351435791805 0.8606062969883559 0.8012199896612426 0.2624697588277912 0.8988531217544283 0.1258892404305789 0.856530667272244 0.824722301542086 0.4538728961955311 0.1280941873938473 0.08219871000674905 0.1741676564028491 0.7274547996552254 0.4869730216040211 0.5069247663715388 0.9199431559224166 0.2154667621352669 0.1358514671089676 0.4418951859799259 0.2220836123568398 0.2360694916915373 0.2753974127693433 0.1381188051918542 0.1763801975353066 0.3723195380032993 0.9867292222969875 0.858851072283221 0.7339912282976964 0.5897746183060495 0.2388350997603985 0.2424297014815817 0.01892396867208657 0.8162613334110634 0.7129250081252332 0.774855080991709 0.2957494121915945 0.7983219144308387 0.5086149638394499 0.1179032359705711 0.8761699753538994 0.2054402327378841 0.2919498044012264 0.290843512338408 0.8754440658250308 0.1609870020247226 0.7228097250791012 0.8055655435127642 0.7418323116947004 0.7920853958298709 0.6978214078652053 0.7784006646895765 0.3651852341851732 0.9096724195139992 0.5531571821179198 0.8564322114391404 0.9575107579546778 0.8050970619317351 0.4179613424010368 0.602931412462276 0.5230608541397703 0.6082975208671643 0.1756052389499451 0.5180545360406706 0.4968258050507409 0.8462128245279992 0.5728063619868741 0.1760462368316695 0.1296960734713823 0.6572523871180592 0.2131182831176431 0.4454183128919467 0.7451889204388251 0.6655099590975496 0.2993956222134874 0.7725552573547741 0.3553950843326966 0.09011994505684695 0.7271792629136289 0.7165184456443356 0.08106656997396422 0.7365092971398089 0.08374574535221657 0.8916906194968202 0.8880889400069596 0.569339413599545 0.8470432410221577 0.126624391351658 0.2047112028112729 0.0494695798458733 0.6923815596490981 0.2932860125924376 0.747849573969439 0.5347389537705853 0.3279230146724041 0.9210220143350989 0.8284653803792299 0.5229904770459297 0.1226789374768018 0.09234004878746749 0.6729606461824392 0.7104310442713989 0.9808680774494408 0.9623490072631435 0.4020676694334012 0.1869150094774705 0.3893541449352056 0.8851191767765655 0.595220050541887 0.6281958266891871 0.9606615428215473 0.2397620720805743 0.3180271638439582 0.2862042183926891 0.9180119294100104 0.8085465726326803 0.9774646258871924 0.1730989274254555 0.8051878535702419 0.3643997132742111 0.5618764948692372 0.2884111060777893 0.7186796644505267 0.3285189118722595 0.6769887600430147 0.8335452742397995 0.04250125038574459 0.9641671066042119 0.1321971985711896 0.1368636163526882 0.6524300048632173 0.330119977126648 0.9776348891326024 0.6633411243322815 0.9156368023687225 0.1441733119922266 0.1040439764128109 0.939679264052967 0.7345261675819142 0.02325974047072077 0.1080733142861334 0.1073453262755185 0.2818173248251982 0.8627800344940149 0.1097552393391756 0.5740891559080574 0.921953095784068 0.9783714131053888 0.9044014136257396 0.05067204470479125 0.4124563188961032 0.3116479265299134 0.4232271462047688 0.9147994258273184 0.284657920925413 0.5749506033568685 0.80654393674224 0.7186282076568636 0.9011443825376279 0.05539105146729706 0.8600983421900328 0.007755462065985763 0.7178897954104533 0.7109009935821109 0.1755371619531991 0.8696552300725474 0.1565621867188104 0.9119635583740171 0.2338083581948056 0.6860592982186901 0.6398985073815359 0.1575943296226382 0.2896859218392631 0.1985220085135001 0.9318124141933212 0.540734493604897 0.9525635271231068 0.2174634830507883 0.6450328825132124 0.7862244324460526 0.4002581097510213 0.8367953789981384 0.1630498009350921 0.2033130762594543 0.343979607240712 0.24913003766186 0.3457013930321183 0.9863802929118149 0.6239507558928402 0.5962644696993289 0.5772919605112458 0.4030340194186339 0.5454462192732453 0.777425284122461 0.4704034911374144 0.08838744941293197 0.9339043281090493 0.04359847705705266 0.6486963416824907 0.733022827726627 0.09322381056555762 0.7855471679755759 0.9248241465898298 0.564250343611759 0.4542472392637262 0.7935355811161912 0.2837788120962224 0.9921018450276777 0.9859792792632424 0.5361795572443926 0.894398466519281 0.2355512730052551 0.4785062946389778 0.9075672387352698 0.6637445253262119 0.43575429373567 0.8539885798482977 0.3960352894920703 0.4686050727239756 0.4499991536423141 0.3239841943808175 0.8708194178746103 0.8832952243422918 0.3430104732742003 0.953920849572316 0.3097282675514356 0.9315138444605948 0.1618978678047657 0.9529393913250206 0.8785188902780843 0.5071705495410398 0.0182444328293786 0.7781547798320358 0.3594572370063724 0.8485491814773263 0.4330620445666292 0.6057818975358047 0.3775799877867961 0.7214100118518808 0.3161731776518653 0.9493514815474066 0.8497458596362656 0.7755979107193002 0.2995165701224971 0.8726990313866313 0.3750827935548919 0.7984195795922602 0.8167874313179456 0.9990129576223229 0.04508877467261807 0.2368026674609457 0.4309058710185842 0.8472399861525521 0.3864352382555887 0.1228069079889299 0.91526185373976 0.1823276543858223 0.5907768634355596 0.8123503247282398 0.2611611475616882 0.985808374756683 0.4412568741065448 0.2252607389802863 0.1847185394374565 0.6982403285717427 0.8751954585254841 0.7689644203263455 0.2614347125582023 0.9857058733591394 0.0441839926335158 0.3441463352947595 0.6731849009464091 0.05673416616913241 0.0545707441021237 0.5648652864788175 0.6509464265538195 0.2370277990419545 0.6269163722820162 0.5300383483457375 0.5142838090737361 0.7016276480583008 0.3736906602422265 0.614033077192303 0.3072869214703424 0.09289696354121046 0.6629214533628009 0.02857520429375648 0.3845448310745404 0.07205191193223814 0.2919184436175765 0.2131595702819035 0.7219973963983469 0.7050250255312476 0.715119919964416 0.3612226449671331 0.5464699797189634 0.3578320102602714 0.9409564116975221 0.4447915352855814 0.1108189395388685 0.8651217656218272 0.03555498797387979 0.2232636532845561 0.1379628655344118 0.3025751230314925 0.254191780954881 0.7311838341926741 0.6376858890976999 0.9752451102282299 0.331082019914313 0.4206910061076482 0.4804255309916361 0.9098342394001943 0.5721246787406048 0.4248358459379435 0.4544178516547929 0.9512078349786919 0.5829458827501757 0.3914352979129718 0.55807778382827 0.9865541073911297 0.7836230392014071 0.08822244423271108 0.3784976622621585 0.7695046155032698 0.1994075438199825 0.3530758331132451 0.2176785000854113 0.003305149718622058 0.1916251113742494 0.4502385355767271 0.6818289194038245 0.4680664799083314 0.1283756856694626 0.8036842883103122 0.07597296795310371 0.1230780971469906 0.8710573958860452 0.6854396413490149 0.5119075462645981 0.6164991191381864 0.8325470008698309 0.01056815712884707 0.5220068211431076 0.3838587544826066 0.05875556671519977 0.7143045209857067 0.7781156166156741 0.7166497352188371 0.1198503775894584 0.3236295747251323 0.8661837429267558 0.6751686521481957 0.2393158308123208 0.02847464195493121 0.2638564538068605 0.7485575826817396 0.4308182999610547 0.9501830906164783 0.08448402435248026 0.01642846671830112 0.6146099219645 0.2135161596821766 0.7536603197850679 0.7120532801956408 0.4065295252711001 0.2429310746985222 0.5293116776533238 0.7923727729025613 0.7715423186598903 0.3729520325404124 arpack-ng-3.3.0/TODO000066400000000000000000000000721260666001200140460ustar00rootroot00000000000000* add a version somewhere to allow configure to detect it arpack-ng-3.3.0/UTIL/000077500000000000000000000000001260666001200141345ustar00rootroot00000000000000arpack-ng-3.3.0/UTIL/Makefile.am000066400000000000000000000004461260666001200161740ustar00rootroot00000000000000SRCS = icnteq.f icopy.f iset.f iswap.f ivout.f second_NONE.f SSRC = svout.f smout.f DSRC = dvout.f dmout.f CSRC = cvout.f cmout.f ZSRC = zvout.f zmout.f EXTRA_DIST = second.f second.t3d noinst_LTLIBRARIES = libarpackutil.la libarpackutil_la_SOURCES = $(SRCS) $(SSRC) $(DSRC) $(CSRC) $(ZSRC) arpack-ng-3.3.0/UTIL/cmout.f000066400000000000000000000210631260666001200154340ustar00rootroot00000000000000* * Routine: CMOUT * * Purpose: Complex matrix output routine. * * Usage: CALL CMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: @(#) * FILE: cmout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2 * *----------------------------------------------------------------------- * SUBROUTINE CMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',E10.3,',',E10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E10.3,',',E10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E12.5,',',E12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E14.7,',',E14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E20.13,',',E20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13, & ') ')) * * * * RETURN END arpack-ng-3.3.0/UTIL/cvout.f000066400000000000000000000200151260666001200154410ustar00rootroot00000000000000c----------------------------------------------------------------------- c c\SCCS Information: @(#) c FILE: cvout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2 c *----------------------------------------------------------------------- * Routine: CVOUT * * Purpose: Complex vector output routine. * * Usage: CALL CVOUT (LOUT, N, CX, IDIGIT, IFMT) * * Arguments * N - Length of array CX. (Input) * CX - Complex array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE CVOUT( LOUT, N, CX, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',E10.3,',',E10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E10.3,',',E10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E10.3,',',E10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E10.3,',',E10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E12.5,',',E12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E12.5,',',E12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E12.5,',',E12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',E14.7,',',E14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E14.7,',',E14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E14.7,',',E14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',E20.13,',',E20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',E20.13,',',E20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/UTIL/dmout.f000066400000000000000000000126571260666001200154460ustar00rootroot00000000000000*----------------------------------------------------------------------- * Routine: DMOUT * * Purpose: Real matrix output routine. * * Usage: CALL DMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Real M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE DMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LDA, LOUT, M, N * .. * .. Array Arguments .. DOUBLE PRECISION A( LDA, * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, J, K1, K2, LLL, NDIGIT * .. * .. Local Arrays .. CHARACTER ICOL( 3 ) * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Data statements .. DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, FMT = 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10D12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8D14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6D18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5D22.13 ) 9990 FORMAT( 1X, ' ' ) * RETURN END arpack-ng-3.3.0/UTIL/dvout.f000066400000000000000000000076041260666001200154530ustar00rootroot00000000000000*----------------------------------------------------------------------- * Routine: DVOUT * * Purpose: Real vector output routine. * * Usage: CALL DVOUT (LOUT, N, SX, IDIGIT, IFMT) * * Arguments * N - Length of array SX. (Input) * SX - Real array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE DVOUT( LOUT, N, SX, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES * .. Scalar Arguments .. CHARACTER*( * ) IFMT INTEGER IDIGIT, LOUT, N * .. * .. Array Arguments .. DOUBLE PRECISION SX( * ) * .. * .. Local Scalars .. CHARACTER*80 LINE INTEGER I, K1, K2, LLL, NDIGIT * .. * .. Intrinsic Functions .. INTRINSIC LEN, MIN, MIN0 * .. * .. Executable Statements .. * ... * ... FIRST EXECUTABLE STATEMENT * * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A, / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, FMT = 9994 ) RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10D12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8D14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6D18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5D24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/UTIL/icnteq.f000066400000000000000000000006041260666001200155660ustar00rootroot00000000000000c c----------------------------------------------------------------------- c c Count the number of elements equal to a specified integer value. c integer function icnteq (n, array, value) c integer n, value integer array(*) c k = 0 do 10 i = 1, n if (array(i) .eq. value) k = k + 1 10 continue icnteq = k c return end arpack-ng-3.3.0/UTIL/icopy.f000066400000000000000000000036351260666001200154350ustar00rootroot00000000000000*-------------------------------------------------------------------- *\Documentation * *\Name: ICOPY * *\Description: * ICOPY copies an integer vector lx to an integer vector ly. * *\Usage: * call icopy ( n, lx, inc, ly, incy ) * *\Arguments: * n integer (input) * On entry, n is the number of elements of lx to be c copied to ly. * * lx integer array (input) * On entry, lx is the integer vector to be copied. * * incx integer (input) * On entry, incx is the increment between elements of lx. * * ly integer array (input) * On exit, ly is the integer vector that contains the * copy of lx. * * incy integer (input) * On entry, incy is the increment between elements of ly. * *\Enddoc * *-------------------------------------------------------------------- * subroutine icopy( n, lx, incx, ly, incy ) * * ---------------------------- * Specifications for arguments * ---------------------------- integer incx, incy, n integer lx( 1 ), ly( 1 ) * * ---------------------------------- * Specifications for local variables * ---------------------------------- integer i, ix, iy * * -------------------------- * First executable statement * -------------------------- if( n.le.0 ) $ return if( incx.eq.1 .and. incy.eq.1 ) $ go to 20 c c.....code for unequal increments or equal increments c not equal to 1 ix = 1 iy = 1 if( incx.lt.0 ) $ ix = ( -n+1 )*incx + 1 if( incy.lt.0 ) $ iy = ( -n+1 )*incy + 1 do 10 i = 1, n ly( iy ) = lx( ix ) ix = ix + incx iy = iy + incy 10 continue return c c.....code for both increments equal to 1 c 20 continue do 30 i = 1, n ly( i ) = lx( i ) 30 continue return end arpack-ng-3.3.0/UTIL/iset.f000066400000000000000000000005051260666001200152470ustar00rootroot00000000000000c c----------------------------------------------------------------------- c c Only work with increment equal to 1 right now. c subroutine iset (n, value, array, inc) c integer n, value, inc integer array(*) c do 10 i = 1, n array(i) = value 10 continue c return end arpack-ng-3.3.0/UTIL/iswap.f000066400000000000000000000023131260666001200154250ustar00rootroot00000000000000 subroutine iswap (n,sx,incx,sy,incy) c c interchanges two vectors. c uses unrolled loops for increments equal to 1. c jack dongarra, linpack, 3/11/78. c integer sx(1),sy(1),stemp integer i,incx,incy,ix,iy,m,mp1,n c if(n.le.0)return if(incx.eq.1.and.incy.eq.1)go to 20 c c code for unequal increments or equal increments not equal c to 1 c ix = 1 iy = 1 if(incx.lt.0)ix = (-n+1)*incx + 1 if(incy.lt.0)iy = (-n+1)*incy + 1 do 10 i = 1,n stemp = sx(ix) sx(ix) = sy(iy) sy(iy) = stemp ix = ix + incx iy = iy + incy 10 continue return c c code for both increments equal to 1 c c c clean-up loop c 20 m = mod(n,3) if( m .eq. 0 ) go to 40 do 30 i = 1,m stemp = sx(i) sx(i) = sy(i) sy(i) = stemp 30 continue if( n .lt. 3 ) return 40 mp1 = m + 1 do 50 i = mp1,n,3 stemp = sx(i) sx(i) = sy(i) sy(i) = stemp stemp = sx(i + 1) sx(i + 1) = sy(i + 1) sy(i + 1) = stemp stemp = sx(i + 2) sx(i + 2) = sy(i + 2) sy(i + 2) = stemp 50 continue return end arpack-ng-3.3.0/UTIL/ivout.f000066400000000000000000000064571260666001200154650ustar00rootroot00000000000000C----------------------------------------------------------------------- C Routine: IVOUT C C Purpose: Integer vector output routine. C C Usage: CALL IVOUT (LOUT, N, IX, IDIGIT, IFMT) C C Arguments C N - Length of array IX. (Input) C IX - Integer array to be printed. (Input) C IFMT - Format to be used in printing array IX. (Input) C IDIGIT - Print up to ABS(IDIGIT) decimal digits / number. (Input) C If IDIGIT .LT. 0, printing is done with 72 columns. C If IDIGIT .GT. 0, printing is done with 132 columns. C C----------------------------------------------------------------------- C SUBROUTINE IVOUT (LOUT, N, IX, IDIGIT, IFMT) C ... C ... SPECIFICATIONS FOR ARGUMENTS INTEGER IX(*), N, IDIGIT, LOUT CHARACTER IFMT*(*) C ... C ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * C LLL = MIN ( LEN ( IFMT ), 80 ) DO 1 I = 1, LLL LINE(I:I) = '-' 1 CONTINUE C DO 2 I = LLL+1, 80 LINE(I:I) = ' ' 2 CONTINUE C WRITE ( LOUT, 2000 ) IFMT, LINE(1:LLL) 2000 FORMAT ( /1X, A /1X, A ) C IF (N .LE. 0) RETURN NDIGIT = IDIGIT IF (IDIGIT .EQ. 0) NDIGIT = 4 C C======================================================================= C CODE FOR OUTPUT USING 72 COLUMNS FORMAT C======================================================================= C IF (IDIGIT .LT. 0) THEN C NDIGIT = -IDIGIT IF (NDIGIT .LE. 4) THEN DO 10 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 10 CONTINUE C ELSE IF (NDIGIT .LE. 6) THEN DO 30 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 30 CONTINUE C ELSE IF (NDIGIT .LE. 10) THEN DO 50 K1 = 1, N, 5 K2 = MIN0(N,K1+4) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 50 CONTINUE C ELSE DO 70 K1 = 1, N, 3 K2 = MIN0(N,K1+2) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 70 CONTINUE END IF C C======================================================================= C CODE FOR OUTPUT USING 132 COLUMNS FORMAT C======================================================================= C ELSE C IF (NDIGIT .LE. 4) THEN DO 90 K1 = 1, N, 20 K2 = MIN0(N,K1+19) WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2) 90 CONTINUE C ELSE IF (NDIGIT .LE. 6) THEN DO 110 K1 = 1, N, 15 K2 = MIN0(N,K1+14) WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2) 110 CONTINUE C ELSE IF (NDIGIT .LE. 10) THEN DO 130 K1 = 1, N, 10 K2 = MIN0(N,K1+9) WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2) 130 CONTINUE C ELSE DO 150 K1 = 1, N, 7 K2 = MIN0(N,K1+6) WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2) 150 CONTINUE END IF END IF WRITE (LOUT,1004) C 1000 FORMAT(1X,I4,' - ',I4,':',20(1X,I5)) 1001 FORMAT(1X,I4,' - ',I4,':',15(1X,I7)) 1002 FORMAT(1X,I4,' - ',I4,':',10(1X,I11)) 1003 FORMAT(1X,I4,' - ',I4,':',7(1X,I15)) 1004 FORMAT(1X,' ') C RETURN END arpack-ng-3.3.0/UTIL/second.f000066400000000000000000000014141260666001200155560ustar00rootroot00000000000000 SUBROUTINE ARSCND( T ) * REAL T * * -- LAPACK auxiliary routine (preliminary version) -- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., * Courant Institute, Argonne National Lab, and Rice University * July 26, 1991 * * Purpose * ======= * * SECOND returns the user time for a process in seconds. * This version gets the time from the system function ETIME. * * .. Local Scalars .. REAL T1 * .. * .. Local Arrays .. REAL TARRAY( 2 ) * .. * .. External Functions .. REAL ETIME INTRINSIC ETIME * .. * .. Executable Statements .. * T1 = ETIME( TARRAY ) T = TARRAY( 1 ) RETURN * * End of ARSCND * END arpack-ng-3.3.0/UTIL/second.t3d000066400000000000000000000001301260666001200160150ustar00rootroot00000000000000 subroutine second(t) real t t = rtc()*6.67E-09 return end arpack-ng-3.3.0/UTIL/second_NONE.f000066400000000000000000000014311260666001200163740ustar00rootroot00000000000000 SUBROUTINE ARSCND( T ) * REAL T * * -- LAPACK auxiliary routine (preliminary version) -- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., * Courant Institute, Argonne National Lab, and Rice University * July 26, 1991 * * Purpose * ======= * * SECOND returns the user time for a process in arscnds. * This version gets the time from the system function ETIME. * * .. Local Scalars .. REAL T1 * .. * .. Local Arrays .. REAL TARRAY( 2 ) * .. * .. External Functions .. REAL ETIME EXTERNAL ETIME * .. * .. Executable Statements .. * c T1 = ETIME( TARRAY ) c T = TARRAY( 1 ) T = 0 RETURN * * End of ARSCND * END arpack-ng-3.3.0/UTIL/smout.f000066400000000000000000000121451260666001200154550ustar00rootroot00000000000000*----------------------------------------------------------------------- * Routine: SMOUT * * Purpose: Real matrix output routine. * * Usage: CALL SMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Real M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE SMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT REAL A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 90 I = 1, M WRITE( LOUT, 9991 )I, ( A( I, J ), J = K1, K2 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.10 ) THEN DO 160 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M WRITE( LOUT, 9991 )I, ( A( I, J ), J = K1, K2 ) 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) ) 9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) ) 9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) ) 9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) ) 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P10E12.3 ) 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P8E14.5 ) 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P6E18.9 ) 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P5E22.13 ) 9990 FORMAT( 1X, ' ' ) * RETURN END arpack-ng-3.3.0/UTIL/svout.f000066400000000000000000000071441260666001200154710ustar00rootroot00000000000000*----------------------------------------------------------------------- * Routine: SVOUT * * Purpose: Real vector output routine. * * Usage: CALL SVOUT (LOUT, N, SX, IDIGIT, IFMT) * * Arguments * N - Length of array SX. (Input) * SX - Real array to be printed. (Input) * IFMT - Format to be used in printing array SX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE SVOUT( LOUT, N, SX, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT REAL SX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 40 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 50 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 50 CONTINUE ELSE DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 10 K2 = MIN0( N, K1+9 ) WRITE( LOUT, 9998 )K1, K2, ( SX( I ), I = K1, K2 ) 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 8 K2 = MIN0( N, K1+7 ) WRITE( LOUT, 9997 )K1, K2, ( SX( I ), I = K1, K2 ) 80 CONTINUE ELSE IF( NDIGIT.LE.10 ) THEN DO 90 K1 = 1, N, 6 K2 = MIN0( N, K1+5 ) WRITE( LOUT, 9996 )K1, K2, ( SX( I ), I = K1, K2 ) 90 CONTINUE ELSE DO 100 K1 = 1, N, 5 K2 = MIN0( N, K1+4 ) WRITE( LOUT, 9995 )K1, K2, ( SX( I ), I = K1, K2 ) 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) RETURN 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P10E12.3 ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P8E14.5 ) 9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P6E18.9 ) 9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P5E24.13 ) 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/UTIL/zmout.f000066400000000000000000000210741260666001200154650ustar00rootroot00000000000000* * Routine: ZMOUT * * Purpose: Complex*16 matrix output routine. * * Usage: CALL ZMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT) * * Arguments * M - Number of rows of A. (Input) * N - Number of columns of A. (Input) * A - Complex*16 M by N matrix to be printed. (Input) * LDA - Leading dimension of A exactly as specified in the * dimension statement of the calling program. (Input) * IFMT - Format to be used in printing matrix A. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *\SCCS Information: @(#) * FILE: zmout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2 * *----------------------------------------------------------------------- * SUBROUTINE ZMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER M, N, IDIGIT, LDA, LOUT Complex*16 & A( LDA, * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, J, NDIGIT, K1, K2, LLL CHARACTER*1 ICOL( 3 ) CHARACTER*80 LINE * ... * ... SPECIFICATIONS INTRINSICS INTRINSIC MIN * DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o', $ 'l' / * ... * ... FIRST EXECUTABLE STATEMENT * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 30 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 ) END IF 30 CONTINUE 40 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 60 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 50 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 ) END IF 50 CONTINUE 60 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 80 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 70 I = 1, M IF (K1.NE.N) THEN WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 ) END IF 70 CONTINUE 80 CONTINUE * ELSE DO 100 K1 = 1, N WRITE( LOUT, 9995 ) ICOL, K1 DO 90 I = 1, M WRITE( LOUT, 9991 )I, A( I, K1 ) 90 CONTINUE 100 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 120 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 ) DO 110 I = 1, M IF ((K1+3).LE.N) THEN WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.1) THEN WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 ) ELSE IF ((K1+3-N).EQ.2) THEN WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+3-N).EQ.3) THEN WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 ) END IF 110 CONTINUE 120 CONTINUE * ELSE IF( NDIGIT.LE.6 ) THEN DO 140 K1 = 1, N, 3 K2 = MIN0( N, K1+ 2) WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 ) DO 130 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 ) END IF 130 CONTINUE 140 CONTINUE * ELSE IF( NDIGIT.LE.8 ) THEN DO 160 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 ) DO 150 I = 1, M IF ((K1+2).LE.N) THEN WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.1) THEN WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 ) ELSE IF ((K1+2-N).EQ.2) THEN WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 ) END IF 150 CONTINUE 160 CONTINUE * ELSE DO 180 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 ) DO 170 I = 1, M IF ((K1+1).LE.N) THEN WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 ) ELSE WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 ) END IF 170 CONTINUE 180 CONTINUE END IF END IF WRITE( LOUT, 9990 ) * 9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) ) 9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) ) 9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) ) 9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) ) * *======================================================== * FORMAT FOR 72 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGITS * 9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13,')') ) 9990 FORMAT( 1X, ' ' ) * * *======================================================== * FORMAT FOR 132 COLUMN *======================================================== * * DISPLAY 4 SIGNIFICANT DIGIT * 9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',D10.3,',',D10.3,') ') ) 9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D10.3,',',D10.3,') ') ) 9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') ) 9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGIT * 9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D12.5,',',D12.5,') ') ) 9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') ) 9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGIT * 9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D14.7,',',D14.7,') ') ) 9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') ) 9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGIT * 9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D20.13,',',D20.13, & ') ')) 9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13, & ') ')) * * * * RETURN END arpack-ng-3.3.0/UTIL/zvout.f000066400000000000000000000200261260666001200154720ustar00rootroot00000000000000c----------------------------------------------------------------------- c c\SCCS Information: @(#) c FILE: zvout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2 c *----------------------------------------------------------------------- * Routine: ZVOUT * * Purpose: Complex*16 vector output routine. * * Usage: CALL ZVOUT (LOUT, N, CX, IDIGIT, IFMT) * * Arguments * N - Length of array CX. (Input) * CX - Complex*16 array to be printed. (Input) * IFMT - Format to be used in printing array CX. (Input) * IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In) * If IDIGIT .LT. 0, printing is done with 72 columns. * If IDIGIT .GT. 0, printing is done with 132 columns. * *----------------------------------------------------------------------- * SUBROUTINE ZVOUT( LOUT, N, CX, IDIGIT, IFMT ) * ... * ... SPECIFICATIONS FOR ARGUMENTS INTEGER N, IDIGIT, LOUT Complex*16 & CX( * ) CHARACTER IFMT*( * ) * ... * ... SPECIFICATIONS FOR LOCAL VARIABLES INTEGER I, NDIGIT, K1, K2, LLL CHARACTER*80 LINE * ... * ... FIRST EXECUTABLE STATEMENT * * LLL = MIN( LEN( IFMT ), 80 ) DO 10 I = 1, LLL LINE( I: I ) = '-' 10 CONTINUE * DO 20 I = LLL + 1, 80 LINE( I: I ) = ' ' 20 CONTINUE * WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL ) 9999 FORMAT( / 1X, A / 1X, A ) * IF( N.LE.0 ) $ RETURN NDIGIT = IDIGIT IF( IDIGIT.EQ.0 ) $ NDIGIT = 4 * *======================================================================= * CODE FOR OUTPUT USING 72 COLUMNS FORMAT *======================================================================= * IF( IDIGIT.LT.0 ) THEN NDIGIT = -IDIGIT IF( NDIGIT.LE.4 ) THEN DO 30 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9998 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9997 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 30 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 40 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9988 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9987 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 40 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 50 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF (K1.NE.N) THEN WRITE( LOUT, 9978 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE WRITE( LOUT, 9977 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 50 CONTINUE ELSE DO 60 K1 = 1, N WRITE( LOUT, 9968 )K1, K1, CX( I ) 60 CONTINUE END IF * *======================================================================= * CODE FOR OUTPUT USING 132 COLUMNS FORMAT *======================================================================= * ELSE IF( NDIGIT.LE.4 ) THEN DO 70 K1 = 1, N, 4 K2 = MIN0( N, K1+3 ) IF ((K1+3).LE.N) THEN WRITE( LOUT, 9958 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9957 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 2) THEN WRITE( LOUT, 9956 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+3-N) .EQ. 1) THEN WRITE( LOUT, 9955 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 70 CONTINUE ELSE IF( NDIGIT.LE.6 ) THEN DO 80 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9948 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9947 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9946 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 80 CONTINUE ELSE IF( NDIGIT.LE.8 ) THEN DO 90 K1 = 1, N, 3 K2 = MIN0( N, K1+2 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9938 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9937 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 2) THEN WRITE( LOUT, 9936 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 90 CONTINUE ELSE DO 100 K1 = 1, N, 2 K2 = MIN0( N, K1+1 ) IF ((K1+2).LE.N) THEN WRITE( LOUT, 9928 )K1, K2, ( CX( I ), $ I = K1, K2 ) ELSE IF ((K1+2-N) .EQ. 1) THEN WRITE( LOUT, 9927 )K1, K2, ( CX( I ), $ I = K1, K2 ) END IF 100 CONTINUE END IF END IF WRITE( LOUT, 9994 ) RETURN * *======================================================================= * FORMAT FOR 72 COLUMNS *======================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * *========================================================================= * FORMAT FOR 132 COLUMNS *========================================================================= * * DISPLAY 4 SIGNIFICANT DIGITS * 9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,4('(',D10.3,',',D10.3,') ') ) 9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D10.3,',',D10.3,') ') ) 9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D10.3,',',D10.3,') ') ) 9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D10.3,',',D10.3,') ') ) * * DISPLAY 6 SIGNIFICANT DIGITS * 9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D12.5,',',D12.5,') ') ) 9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D12.5,',',D12.5,') ') ) 9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D12.5,',',D12.5,') ') ) * * DISPLAY 8 SIGNIFICANT DIGITS * 9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,3('(',D14.7,',',D14.7,') ') ) 9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D14.7,',',D14.7,') ') ) 9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D14.7,',',D14.7,') ') ) * * DISPLAY 13 SIGNIFICANT DIGITS * 9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,2('(',D20.13,',',D20.13,') ') ) 9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X, $ 1P,1('(',D20.13,',',D20.13,') ') ) * * * 9994 FORMAT( 1X, ' ' ) END arpack-ng-3.3.0/VISUAL_STUDIO/000077500000000000000000000000001260666001200154515ustar00rootroot00000000000000arpack-ng-3.3.0/VISUAL_STUDIO/arpack-ng.rc000066400000000000000000000035061260666001200176460ustar00rootroot00000000000000//Microsoft Developer Studio generated resource script. // #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" #include "winver.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Neutral resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #pragma code_page(1252) #endif //_WIN32 #endif // Neutral resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "#include ""winver.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN 0 " " END #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED arpack-ng-3.3.0/VISUAL_STUDIO/arpack-ng.sln000066400000000000000000000037531260666001200200420ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "arpack-ng", "arpack-ng.vfproj", "{34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug MKL|Win32 = Debug MKL|Win32 Debug MKL|x64 = Debug MKL|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release MKL|Win32 = Release MKL|Win32 Release MKL|x64 = Release MKL|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug MKL|Win32.ActiveCfg = Debug MKL|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug MKL|Win32.Build.0 = Debug MKL|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug MKL|x64.ActiveCfg = Debug MKL|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug MKL|x64.Build.0 = Debug MKL|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug|Win32.ActiveCfg = Debug|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug|Win32.Build.0 = Debug|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug|x64.ActiveCfg = Debug|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Debug|x64.Build.0 = Debug|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release MKL|Win32.ActiveCfg = Release MKL|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release MKL|Win32.Build.0 = Release MKL|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release MKL|x64.ActiveCfg = Release MKL|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release MKL|x64.Build.0 = Release MKL|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release|Win32.ActiveCfg = Release|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release|Win32.Build.0 = Release|Win32 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release|x64.ActiveCfg = Release|x64 {34F953E3-9A2C-4359-A8C5-41CEBD0ECE45}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal arpack-ng-3.3.0/VISUAL_STUDIO/arpack-ng.vfproj000066400000000000000000000444361260666001200205570ustar00rootroot00000000000000 arpack-ng-3.3.0/VISUAL_STUDIO/arpack-ng_exports.def000066400000000000000000000006401260666001200215600ustar00rootroot00000000000000LIBRARY arpack-ng.dll EXPORTS cmout_ cvout_ dgetv0_ dlaqrb_ dmout_ dnaitr_ dnapps_ dnaup2_ dnaupd_ dnconv_ dneigh_ dneupd_ dngets_ dsaitr_ dsapps_ dsaup2_ dsaupd_ dsconv_ dseigt_ dsesrt_ dseupd_ dsgets_ dsortc_ dsortr_ dstatn_ dstats_ dstqrb_ dvout_ icnteq_ iswap_ ivout_ arscnd_ smout_ zgetv0_ znaitr_ znapps_ znaup2_ znaupd_ zneigh_ zneupd_ zngets_ zsortc_ zstatn_ arpack-ng-3.3.0/VISUAL_STUDIO/blas_imports.def000066400000000000000000000032641260666001200206340ustar00rootroot00000000000000LIBRARY blas.dll EXPORTS dasum_ dasum = dasum_ daxpy_ daxpy = daxpy_ dcopy_ dcopy = dcopy_ ddot_ ddot = ddot_ dgbmv_ dgbmv = dgbmv_ dgemm_ dgemm = dgemm_ dgemv_ dgemv = dgemv_ dger_ dger = dger_ dnrm2_ dnrm2 = dnrm2_ drot_ drot = drot_ drotg_ drotg = drotg_ dsbmv_ dsbmv = dsbmv_ dscal_ dscal = dscal_ dspmv_ dspmv = dspmv_ dspr_ dspr = dspr_ dspr2_ dspr2 = dspr2_ dswap_ dswap = dswap_ dsymm_ dsymm = dsymm_ dsymv_ dsymv = dsymv_ dsyr_ dsyr = dsyr_ dsyr2_ dsyr2 = dsyr2_ dsyr2k_ dsyr2k = dsyr2k_ dsyrk_ dsyrk = dsyrk_ dtbmv_ dtbmv = dtbmv_ dtbsv_ dtbsv = dtbsv_ dtpmv_ dtpmv = dtpmv_ dtpsv_ dtpsv = dtpsv_ dtrmm_ dtrmm = dtrmm_ dtrmv_ dtrmv = dtrmv_ dtrsm_ dtrsm = dtrsm_ dtrsv_ dtrsv = dtrsv_ dzasum_ dzasum = dzasum_ dznrm2_ dznrm2 = dznrm2_ idamax_ idamax = idamax_ izamax_ izamax = izamax_ zaxpy_ zaxpy = zaxpy_ zcopy_ zcopy = zcopy_ zdotc_ zdotc = zdotc_ zdotu_ zdotu = zdotu_ zdscal_ zdscal = zdscal_ zgbmv_ zgbmv = zgbmv_ zgemm_ zgemm = zgemm_ zgemv_ zgemv = zgemv_ zgerc_ zgerc = zgerc_ zgeru_ zgeru = zgeru_ zhbmv_ zhbmv = zhbmv_ zhemm_ zhemm = zhemm_ zhemv_ zhemv = zhemv_ zher_ zher = zher_ zher2_ zher2 = zher2_ zher2k_ zher2k = zher2k_ zherk_ zherk = zherk_ zhpmv_ zhpmv = zhpmv_ zhpr_ zhpr = zhpr_ zhpr2_ zhpr2 = zhpr2_ zrotg_ zrotg = zrotg_ zscal_ zscal = zscal_ zswap_ zswap = zswap_ zsymm_ zsymm = zsymm_ zsyr2k_ zsyr2k = zsyr2k_ zsyrk_ zsyrk = zsyrk_ ztbmv_ ztbmv = ztbmv_ ztbsv_ ztbsv = ztbsv_ ztpmv_ ztpmv = ztpmv_ ztpsv_ ztpsv = ztpsv_ ztrmm_ ztrmm =ztrmm_ ztrmv_ ztrmv = ztrmv_ ztrsm_ ztrsm = ztrsm_ ztrsv_ ztrsv = ztrsv_ xerbla_ xerbla = xerbla_ arpack-ng-3.3.0/VISUAL_STUDIO/blasplus_imports.def000066400000000000000000000052211260666001200215330ustar00rootroot00000000000000LIBRARY blasplus.dll EXPORTS dasum_ @1 dasum = dasum_ daxpy_ @2 daxpy = daxpy_ dcopy_ @3 dcopy = dcopy_ ddot_ @4 ddot = ddot_ dgbmv_ @5 dgbmv = dgbmv_ dgemm_ @6 dgemm = dgemm_ dgemv_ @7 dgemv = dgemv_ dger_ @8 dger = dger_ dnrm2_ @9 dnrm2 = dnrm2_ drot_ @10 drot = drot_ drotg_ @11 drotg = drotg_ dsbmv_ @12 dsbmv = dsbmv_ dscal_ @13 dscal = dscal_ dspmv_ @14 dspmv = dspmv_ dspr_ @15 dspr = dspr_ dspr2_ @16 dspr2 = dspr2_ dswap_ @17 dswap = dswap_ dsymm_ @18 dsymm = dsymm_ dsymv_ @19 dsymv = dsymv_ dsyr_ @20 dsyr = dsyr_ dsyr2_ @21 dsyr2 = dsyr2_ dsyr2k_ @22 dsyr2k = dsyr2k_ dsyrk_ @23 dsyrk = dsyrk_ dtbmv_ @24 dtbmv = dtbmv_ dtbsv_ @25 dtbsv = dtbsv_ dtpmv_ @26 dtpmv = dtpmv_ dtpsv_ @27 dtpsv = dtpsv_ dtrmm_ @28 dtrmm = dtrmm_ dtrmv_ @29 dtrmv = dtrmv_ dtrsm_ @30 dtrsm = dtrsm_ dtrsv_ @31 dtrsv = dtrsv_ dzasum_ @32 dzasum = dzasum_ dznrm2_ @33 dznrm2 = dznrm2_ idamax_ @34 idamax = idamax_ izamax_ @35 izamax = izamax_ xerbla_ @36 xerbla = xerbla_ zaxpy_ @37 zaxpy = zaxpy_ zcopy_ @38 zcopy = zcopy_ zdotc_ @39 zdotc = zdotc_ zdotu_ @40 zdotu = zdotu_ zdscal_ @41 zdscal = zdscal_ zgbmv_ @42 zgbmv = zgbmv_ zgemm_ @43 zgemm = zgemm_ zgemv_ @44 zgemv = zgemv_ zgerc_ @45 zgerc = zgerc_ zgeru_ @46 zgeru = zgeru_ zhbmv_ @47 zhbmv = zhbmv_ zhemm_ @48 zhemm = zhemm_ zhemv_ @49 zhemv = zhemv_ zher_ @50 zher = zher_ zher2_ @51 zher2 = zher2_ zher2k_ @52 zher2k = zher2k_ zherk_ @53 zherk = zherk_ zhpmv_ @54 zhpmv = zhpmv_ zhpr_ @55 zhpr = zhpr_ zhpr2_ @56 zhpr2 = zhpr2_ zrotg_ @57 zrotg = zrotg_ zscal_ @58 zscal = zscal_ zswap_ @59 zswap = zswap_ zsymm_ @60 zsymm = zsymm_ zsyr2k_ @61 zsyr2k = zsyr2k_ zsyrk_ @62 zsyrk = zsyrk_ ztbmv_ @63 ztbmv = ztbmv_ ztbsv_ @64 ztbsv = ztbsv_ ztpmv_ @65 ztpmv = ztpmv_ ztpsv_ @66 ztpsv = ztpsv_ ztrmm_ @67 ztrmm =ztrmm_ ztrmv_ @68 ztrmv = ztrmv_ ztrsm_ @69 ztrsm = ztrsm_ ztrsv_ @70 ztrsv = ztrsv_ arpack-ng-3.3.0/VISUAL_STUDIO/lapack_imports.def000066400000000000000000000013321260666001200211400ustar00rootroot00000000000000LIBRARY lapack.dll EXPORTS dlamch_ dlapy2_ zlaset_ zlahqr_ ztrsen_ zgeqr2_ zunm2r_ zlacpy_ ztrevc_ dlabad_ dlaset_ dlanhs_ dlartg_ dlarfg_ dlarf_ dlarnv_ dlaruv_ dlacpy_ dswap_ dlascl_ dtrevc_ dlanst_ dlaev2_ dlae2_ dlasr_ dlasrt_ zlascl_ zlanhs_ dsteqr_ dgeqr2_ dorm2r_ dlahqr_ dtrsen_ dlanv2_ zlarnv_ zlartg_ ; slamch_ slapy2_ cswap_ slabad_ claset_ slarf_ strmm_ strevc_ strsen_ slahqr_ saxpy_ sger_ slacpy_ sorm2r_ sgeqr2_ ssteqr_ slaset_ slasrt_ slartg_ slae2_ slasr_ slaev2_ slascl_ slanst_ sscal_ clarnv_ sswap_ cgeru_ ctrmm_ ctrevc_ clanhs_ clartg_ cscal_ cgemv_ ccopy_ clacpy_ caxpy_ slanhs_ scopy_ slarfg_ slanv2_ srot_ csscal_ clascl_ cdotc_ scnrm2_ slarnv_ sdot_ snrm2_ sgemv_ clahqr_ ctrsen_ cgeqr2_ cunm2r_ arpack-ng-3.3.0/arpack.pc.in000066400000000000000000000004441260666001200155530ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ Name: @PACKAGE_NAME@ Description: Collection of Fortran77 subroutines designed to solve large scale eigenvalue problems Version: @PACKAGE_VERSION@ URL: @PACKAGE_URL@ Libs: -L${libdir} -larpack Libs.private: @LAPACK_LIBS@ @BLAS_LIBS@ arpack-ng-3.3.0/bootstrap000077500000000000000000000000331260666001200153160ustar00rootroot00000000000000#!/bin/sh autoreconf -vif arpack-ng-3.3.0/configure.ac000066400000000000000000000033061260666001200156470ustar00rootroot00000000000000AC_PREREQ(2.59) AC_INIT([ARPACK-NG],[3.3.0],[https://github.com/opencollab/arpack-ng/issues/],[arpack-ng],[https://github.com/opencollab/arpack-ng/]) AM_INIT_AUTOMAKE([foreign]) AM_MAINTAINER_MODE AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_LINKS([TESTS/testA.mtx:TESTS/testA.mtx]) dnl Checks for standard programs. AC_PROG_F77 AC_PROG_CC ifdef([LT_INIT], [], [ errprint([error: you must have libtool 2.4.2 or a more recent version ]) m4exit([1])]) LT_PREREQ([2.4.2]) LT_INIT([win32-dll]) dnl Check for BLAS libraries sinclude(ax_blas.m4) AX_BLAS if test "$ax_blas_ok" = "no"; then AC_MSG_ERROR([Cannot find BLAS libraries]) fi dnl Check for LAPACK libraries sinclude(ax_lapack.m4) AX_LAPACK if test "$ax_lapack_ok" = "no"; then AC_MSG_ERROR([Cannot find LAPACK libraries]) fi dnl See if compiling parpack AC_MSG_CHECKING([for MPI mode]) AC_ARG_ENABLE(mpi, AC_HELP_STRING([--enable-mpi], [build parallel version of arpack with MPI]), [enable_mpi=$enableval], [enable_mpi=no]) if test x"$enable_mpi" != x"no"; then AC_LANG_PUSH([Fortran 77]) AX_MPI([], AC_MSG_ERROR([could not compile a MPI test program])) AC_LANG_POP([Fortran 77]) fi AM_CONDITIONAL(MPI, test x"$enable_mpi" = x"yes") AC_CONFIG_FILES([ arpack.pc Makefile SRC/Makefile UTIL/Makefile TESTS/Makefile EXAMPLES/Makefile EXAMPLES/BAND/Makefile EXAMPLES/COMPLEX/Makefile EXAMPLES/NONSYM/Makefile EXAMPLES/SIMPLE/Makefile EXAMPLES/SVD/Makefile EXAMPLES/SYM/Makefile PARPACK/Makefile PARPACK/SRC/Makefile PARPACK/SRC/MPI/Makefile PARPACK/SRC/BLACS/Makefile PARPACK/UTIL/Makefile PARPACK/UTIL/MPI/Makefile PARPACK/UTIL/BLACS/Makefile PARPACK/EXAMPLES/MPI/Makefile PARPACK/EXAMPLES/BLACS/Makefile ]) AC_OUTPUT arpack-ng-3.3.0/detect_arpack_bug.m4000066400000000000000000000110731260666001200172510ustar00rootroot00000000000000dnl dnl Check whether ARPACK works (does not crash) dnl dnl Using a pure Fortran program doesn't seem to crash when linked dnl with the buggy ARPACK library but the C++ program does. Maybe dnl it is the memory allocation that exposes the bug and using statically dnl allocated arrays in Fortran does not? dnl dnl This code is not used by arpack-ng itself. dnl This is a macro for applications using arpack to detect that the version dnl of arpack behave correcly (ie not arpack-ng) dnl This is the work of Rik dnl dnl This code is released under the same license as arpack dnl AC_DEFUN([CHECK_ARPACK_OK], [ AC_LANG_PUSH(C++) AC_CACHE_CHECK([whether the arpack library works], [cv_lib_arpack_ok], [ AC_RUN_IFELSE([AC_LANG_PROGRAM([[ // External functions from ARPACK library extern "C" int F77_FUNC (dnaupd, DNAUPD) (int&, const char *, const int&, const char *, int&, const double&, double*, const int&, double*, const int&, int*, int*, double*, double*, const int&, int&, long int, long int); extern "C" int F77_FUNC (dneupd, DNEUPD) (const int&, const char *, int*, double*, double*, double*, const int&, const double&, const double&, double*, const char*, const int&, const char *, int&, const double&, double*, const int&, double*, const int&, int*, int*, double*, double*, const int&, int&, long int, long int, long int); extern "C" int F77_FUNC (dgemv, DGEMV) (const char *, const int&, const int&, const double&, const double*, const int&, const double*, const int&, const double&, double*, const int&, long int); #include void doit (void) { // Based on the octave function EigsRealNonSymmetricMatrix from // liboctave/eigs-base.cc. // Problem matrix. See bug #31479 int n = 4; double *m = new double [n * n]; m[0] = 1, m[4] = 0, m[8] = 0, m[12] = -1; m[1] = 0, m[5] = 1, m[9] = 0, m[13] = 0; m[2] = 0, m[6] = 0, m[10] = 1, m[14] = 0; m[3] = 0, m[7] = 0, m[11] = 2, m[15] = 1; double *resid = new double [4]; resid[0] = 0.960966; resid[1] = 0.741195; resid[2] = 0.150143; resid[3] = 0.868067; int *ip = new int [11]; ip[0] = 1; // ishift ip[1] = 0; // ip[1] not referenced ip[2] = 300; // mxiter, maximum number of iterations ip[3] = 1; // NB blocksize in recurrence ip[4] = 0; // nconv, number of Ritz values that satisfy convergence ip[5] = 0; // ip[5] not referenced ip[6] = 1; // mode ip[7] = 0; // ip[7] to ip[10] are return values ip[8] = 0; ip[9] = 0; ip[10] = 0; int *ipntr = new int [14]; int k = 1; int p = 3; int lwork = 3 * p * (p + 2); double *v = new double [n * (p + 1)]; double *workl = new double [lwork + 1]; double *workd = new double [3 * n + 1]; int ido = 0; int info = 0; double tol = DBL_EPSILON; do { F77_FUNC (dnaupd, DNAUPD) (ido, "I", n, "LM", k, tol, resid, p, v, n, ip, ipntr, workd, workl, lwork, info, 1L, 2L); if (ido == -1 || ido == 1 || ido == 2) { double *x = workd + ipntr[0] - 1; double *y = workd + ipntr[1] - 1; F77_FUNC (dgemv, DGEMV) ("N", n, n, 1.0, m, n, x, 1, 0.0, y, 1, 1L); } else { if (info < 0) { return; // Error } break; } } while (1); int *sel = new int [p]; // In Octave, the dimensions of dr and di are k+1, but k+2 avoids segfault double *dr = new double [k + 1]; double *di = new double [k + 1]; double *workev = new double [3 * p]; for (int i = 0; i < k + 1; i++) dr[i] = di[i] = 0.; int rvec = 1; double sigmar = 0.0; double sigmai = 0.0; // In Octave, this is n*(k+1), but k+2 avoids segfault double *z = new double [n * (k + 1)]; F77_FUNC (dneupd, DNEUPD) (rvec, "A", sel, dr, di, z, n, sigmar, sigmai, workev, "I", n, "LM", k, tol, resid, p, v, n, ip, ipntr, workd, workl, lwork, info, 1L, 1L, 2L); } ]], [[ for (int i = 0; i < 10; i++) doit (); ]])], [cv_lib_arpack_ok=yes], [cv_lib_arpack_ok=no], [cv_lib_arpack_ok=yes])]) AC_LANG_POP(C++) if test "$cv_lib_arpack_ok" = "yes"; then $1 else $2 fi ]) arpack-ng-3.3.0/m4/000077500000000000000000000000001260666001200136775ustar00rootroot00000000000000arpack-ng-3.3.0/m4/ax_blas.m4000066400000000000000000000176511260666001200155640ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_blas.html # =========================================================================== # # SYNOPSIS # # AX_BLAS([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro looks for a library that implements the BLAS linear-algebra # interface (see http://www.netlib.org/blas/). On success, it sets the # BLAS_LIBS output variable to hold the requisite library linkages. # # To link with BLAS, you should link with: # # $BLAS_LIBS $LIBS $FLIBS # # in that order. FLIBS is the output variable of the # AC_F77_LIBRARY_LDFLAGS macro (called if necessary by AX_BLAS), and is # sometimes necessary in order to link with F77 libraries. Users will also # need to use AC_F77_DUMMY_MAIN (see the autoconf manual), for the same # reason. # # Many libraries are searched for, from ATLAS to CXML to ESSL. The user # may also use --with-blas= in order to use some specific BLAS # library . In order to link successfully, however, be aware that you # will probably need to use the same Fortran compiler (which can be set # via the F77 env. var.) as was used to compile the BLAS library. # # ACTION-IF-FOUND is a list of shell commands to run if a BLAS library is # found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is # not found. If ACTION-IF-FOUND is not specified, the default action will # define HAVE_BLAS. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 14 AU_ALIAS([ACX_BLAS], [AX_BLAS]) AC_DEFUN([AX_BLAS], [ AC_PREREQ(2.50) AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) AC_REQUIRE([AC_CANONICAL_HOST]) ax_blas_ok=no AC_ARG_WITH(blas, [AS_HELP_STRING([--with-blas=], [use BLAS library ])]) case $with_blas in yes | "") ;; no) ax_blas_ok=disable ;; -* | */* | *.a | *.so | *.so.* | *.o) BLAS_LIBS="$with_blas" ;; *) BLAS_LIBS="-l$with_blas" ;; esac # Get fortran linker names of BLAS functions to check for. AC_F77_FUNC(sgemm) AC_F77_FUNC(dgemm) ax_blas_save_LIBS="$LIBS" LIBS="$LIBS $FLIBS" # First, check BLAS_LIBS environment variable if test $ax_blas_ok = no; then if test "x$BLAS_LIBS" != x; then save_LIBS="$LIBS"; LIBS="$BLAS_LIBS $LIBS" AC_MSG_CHECKING([for $sgemm in $BLAS_LIBS]) AC_TRY_LINK_FUNC($sgemm, [ax_blas_ok=yes], [BLAS_LIBS=""]) AC_MSG_RESULT($ax_blas_ok) LIBS="$save_LIBS" fi fi # BLAS linked to by default? (happens on some supercomputers) if test $ax_blas_ok = no; then save_LIBS="$LIBS"; LIBS="$LIBS" AC_MSG_CHECKING([if $sgemm is being linked in already]) AC_TRY_LINK_FUNC($sgemm, [ax_blas_ok=yes]) AC_MSG_RESULT($ax_blas_ok) LIBS="$save_LIBS" fi # BLAS in OpenBLAS library? (http://xianyi.github.com/OpenBLAS/) if test $ax_blas_ok = no; then AC_CHECK_LIB(openblas, $sgemm, [ax_blas_ok=yes BLAS_LIBS="-lopenblas"]) fi # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/) if test $ax_blas_ok = no; then AC_CHECK_LIB(atlas, ATL_xerbla, [AC_CHECK_LIB(f77blas, $sgemm, [AC_CHECK_LIB(cblas, cblas_dgemm, [ax_blas_ok=yes BLAS_LIBS="-lcblas -lf77blas -latlas"], [], [-lf77blas -latlas])], [], [-latlas])]) fi # BLAS in PhiPACK libraries? (requires generic BLAS lib, too) if test $ax_blas_ok = no; then AC_CHECK_LIB(blas, $sgemm, [AC_CHECK_LIB(dgemm, $dgemm, [AC_CHECK_LIB(sgemm, $sgemm, [ax_blas_ok=yes; BLAS_LIBS="-lsgemm -ldgemm -lblas"], [], [-lblas])], [], [-lblas])]) fi # BLAS in Intel MKL library? if test $ax_blas_ok = no; then # MKL for gfortran if test x"$ac_cv_fc_compiler_gnu" = xyes; then # 64 bit if test $host_cpu = x86_64; then AC_CHECK_LIB(mkl_gf_lp64, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lmkl_gf_lp64 -lmkl_sequential -lmkl_core -lpthread"],, [-lmkl_gf_lp64 -lmkl_sequential -lmkl_core -lpthread]) # 32 bit elif test $host_cpu = i686; then AC_CHECK_LIB(mkl_gf, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lmkl_gf -lmkl_sequential -lmkl_core -lpthread"],, [-lmkl_gf -lmkl_sequential -lmkl_core -lpthread]) fi # MKL for other compilers (Intel, PGI, ...?) else # 64-bit if test $host_cpu = x86_64; then AC_CHECK_LIB(mkl_intel_lp64, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread"],, [-lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread]) # 32-bit elif test $host_cpu = i686; then AC_CHECK_LIB(mkl_intel, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lmkl_intel -lmkl_sequential -lmkl_core -lpthread"],, [-lmkl_intel -lmkl_sequential -lmkl_core -lpthread]) fi fi fi # Old versions of MKL if test $ax_blas_ok = no; then AC_CHECK_LIB(mkl, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lmkl -lguide -lpthread"],,[-lguide -lpthread]) fi # BLAS in Apple vecLib library? if test $ax_blas_ok = no; then save_LIBS="$LIBS"; LIBS="-framework vecLib $LIBS" AC_MSG_CHECKING([for $sgemm in -framework vecLib]) AC_TRY_LINK_FUNC($sgemm, [ax_blas_ok=yes;BLAS_LIBS="-framework vecLib"]) AC_MSG_RESULT($ax_blas_ok) LIBS="$save_LIBS" fi # BLAS in Alpha CXML library? if test $ax_blas_ok = no; then AC_CHECK_LIB(cxml, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-lcxml"]) fi # BLAS in Alpha DXML library? (now called CXML, see above) if test $ax_blas_ok = no; then AC_CHECK_LIB(dxml, $sgemm, [ax_blas_ok=yes;BLAS_LIBS="-ldxml"]) fi # BLAS in Sun Performance library? if test $ax_blas_ok = no; then if test "x$GCC" != xyes; then # only works with Sun CC AC_CHECK_LIB(sunmath, acosp, [AC_CHECK_LIB(sunperf, $sgemm, [BLAS_LIBS="-xlic_lib=sunperf -lsunmath" ax_blas_ok=yes],[],[-lsunmath])]) fi fi # BLAS in SCSL library? (SGI/Cray Scientific Library) if test $ax_blas_ok = no; then AC_CHECK_LIB(scs, $sgemm, [ax_blas_ok=yes; BLAS_LIBS="-lscs"]) fi # BLAS in SGIMATH library? if test $ax_blas_ok = no; then AC_CHECK_LIB(complib.sgimath, $sgemm, [ax_blas_ok=yes; BLAS_LIBS="-lcomplib.sgimath"]) fi # BLAS in IBM ESSL library? (requires generic BLAS lib, too) if test $ax_blas_ok = no; then AC_CHECK_LIB(blas, $sgemm, [AC_CHECK_LIB(essl, $sgemm, [ax_blas_ok=yes; BLAS_LIBS="-lessl -lblas"], [], [-lblas $FLIBS])]) fi # Generic BLAS library? if test $ax_blas_ok = no; then AC_CHECK_LIB(blas, $sgemm, [ax_blas_ok=yes; BLAS_LIBS="-lblas"]) fi AC_SUBST(BLAS_LIBS) LIBS="$ax_blas_save_LIBS" # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_blas_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_BLAS,1,[Define if you have a BLAS library.]),[$1]) : else ax_blas_ok=no $2 fi ])dnl AX_BLAS arpack-ng-3.3.0/m4/ax_lapack.m4000066400000000000000000000116601260666001200160700ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_lapack.html # =========================================================================== # # SYNOPSIS # # AX_LAPACK([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro looks for a library that implements the LAPACK linear-algebra # interface (see http://www.netlib.org/lapack/). On success, it sets the # LAPACK_LIBS output variable to hold the requisite library linkages. # # To link with LAPACK, you should link with: # # $LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS # # in that order. BLAS_LIBS is the output variable of the AX_BLAS macro, # called automatically. FLIBS is the output variable of the # AC_F77_LIBRARY_LDFLAGS macro (called if necessary by AX_BLAS), and is # sometimes necessary in order to link with F77 libraries. Users will also # need to use AC_F77_DUMMY_MAIN (see the autoconf manual), for the same # reason. # # The user may also use --with-lapack= in order to use some specific # LAPACK library . In order to link successfully, however, be aware # that you will probably need to use the same Fortran compiler (which can # be set via the F77 env. var.) as was used to compile the LAPACK and BLAS # libraries. # # ACTION-IF-FOUND is a list of shell commands to run if a LAPACK library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_LAPACK. # # LICENSE # # Copyright (c) 2009 Steven G. Johnson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AU_ALIAS([ACX_LAPACK], [AX_LAPACK]) AC_DEFUN([AX_LAPACK], [ AC_REQUIRE([AX_BLAS]) ax_lapack_ok=no AC_ARG_WITH(lapack, [AS_HELP_STRING([--with-lapack=], [use LAPACK library ])]) case $with_lapack in yes | "") ;; no) ax_lapack_ok=disable ;; -* | */* | *.a | *.so | *.so.* | *.o) LAPACK_LIBS="$with_lapack" ;; *) LAPACK_LIBS="-l$with_lapack" ;; esac # Get fortran linker name of LAPACK function to check for. AC_F77_FUNC(cheev) # We cannot use LAPACK if BLAS is not found if test "x$ax_blas_ok" != xyes; then ax_lapack_ok=noblas LAPACK_LIBS="" fi # First, check LAPACK_LIBS environment variable if test "x$LAPACK_LIBS" != x; then save_LIBS="$LIBS"; LIBS="$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS" AC_MSG_CHECKING([for $cheev in $LAPACK_LIBS]) AC_TRY_LINK_FUNC($cheev, [ax_lapack_ok=yes], [LAPACK_LIBS=""]) AC_MSG_RESULT($ax_lapack_ok) LIBS="$save_LIBS" if test $ax_lapack_ok = no; then LAPACK_LIBS="" fi fi # LAPACK linked to by default? (is sometimes included in BLAS lib) if test $ax_lapack_ok = no; then save_LIBS="$LIBS"; LIBS="$LIBS $BLAS_LIBS $FLIBS" AC_CHECK_FUNC($cheev, [ax_lapack_ok=yes]) LIBS="$save_LIBS" fi # Generic LAPACK library? for lapack in lapack lapack_rs6k; do if test $ax_lapack_ok = no; then save_LIBS="$LIBS"; LIBS="$BLAS_LIBS $LIBS" AC_CHECK_LIB($lapack, $cheev, [ax_lapack_ok=yes; LAPACK_LIBS="-l$lapack"], [], [$FLIBS]) LIBS="$save_LIBS" fi done AC_SUBST(LAPACK_LIBS) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_lapack_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_LAPACK,1,[Define if you have LAPACK library.]),[$1]) : else ax_lapack_ok=no $2 fi ])dnl AX_LAPACK arpack-ng-3.3.0/m4/ax_mpi.m4000066400000000000000000000153611260666001200154240ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_mpi.html # =========================================================================== # # SYNOPSIS # # AX_MPI([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro tries to find out how to compile programs that use MPI # (Message Passing Interface), a standard API for parallel process # communication (see http://www-unix.mcs.anl.gov/mpi/) # # On success, it sets the MPICC, MPICXX, MPIF77, or MPIFC output variable # to the name of the MPI compiler, depending upon the current language. # (This may just be $CC/$CXX/$F77/$FC, but is more often something like # mpicc/mpiCC/mpif77/mpif90.) It also sets MPILIBS to any libraries that # are needed for linking MPI (e.g. -lmpi or -lfmpi, if a special # MPICC/MPICXX/MPIF77/MPIFC was not found). # # If you want to compile everything with MPI, you should use something # like this for C: # # if test -z "$CC" && test -n "$MPICC"; then # CC="$MPICC" # fi # AC_PROG_CC # AX_MPI # CC="$MPICC" # LIBS="$MPILIBS $LIBS" # # and similar for C++ (change all instances of CC to CXX), Fortran 77 # (with F77 instead of CC) or Fortran (with FC instead of CC). # # NOTE: The above assumes that you will use $CC (or whatever) for linking # as well as for compiling. (This is the default for automake and most # Makefiles.) # # The user can force a particular library/compiler by setting the # MPICC/MPICXX/MPIF77/MPIFC and/or MPILIBS environment variables. # # ACTION-IF-FOUND is a list of shell commands to run if an MPI library is # found, and ACTION-IF-NOT-FOUND is a list of commands to run if it is not # found. If ACTION-IF-FOUND is not specified, the default action will # define HAVE_MPI. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Julian C. Cummings # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AU_ALIAS([ACX_MPI], [AX_MPI]) AC_DEFUN([AX_MPI], [ AC_PREREQ(2.50) dnl for AC_LANG_CASE AC_LANG_CASE([C], [ AC_REQUIRE([AC_PROG_CC]) AC_ARG_VAR(MPICC,[MPI C compiler command]) AC_CHECK_PROGS(MPICC, mpicc hcc mpxlc_r mpxlc mpcc cmpicc, $CC) ax_mpi_save_CC="$CC" CC="$MPICC" AC_SUBST(MPICC) ], [C++], [ AC_REQUIRE([AC_PROG_CXX]) AC_ARG_VAR(MPICXX,[MPI C++ compiler command]) AC_CHECK_PROGS(MPICXX, mpic++ mpicxx mpiCC hcp mpxlC_r mpxlC mpCC cmpic++, $CXX) ax_mpi_save_CXX="$CXX" CXX="$MPICXX" AC_SUBST(MPICXX) ], [Fortran 77], [ AC_REQUIRE([AC_PROG_F77]) AC_ARG_VAR(MPIF77,[MPI Fortran 77 compiler command]) AC_CHECK_PROGS(MPIF77, mpif77 hf77 mpxlf_r mpxlf mpf77 cmpifc, $F77) ax_mpi_save_F77="$F77" F77="$MPIF77" AC_SUBST(MPIF77) ], [Fortran], [ AC_REQUIRE([AC_PROG_FC]) AC_ARG_VAR(MPIFC,[MPI Fortran compiler command]) AC_CHECK_PROGS(MPIFC, mpif90 mpxlf95_r mpxlf90_r mpxlf95 mpxlf90 mpf90 cmpif90c, $FC) ax_mpi_save_FC="$FC" FC="$MPIFC" AC_SUBST(MPIFC) ]) if test x = x"$MPILIBS"; then AC_LANG_CASE([C], [AC_CHECK_FUNC(MPI_Init, [MPILIBS=" "])], [C++], [AC_CHECK_FUNC(MPI_Init, [MPILIBS=" "])], [Fortran 77], [AC_MSG_CHECKING([for MPI_Init]) AC_LINK_IFELSE([AC_LANG_PROGRAM([],[ call MPI_Init])],[MPILIBS="" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)])], [Fortran], [AC_MSG_CHECKING([for MPI_Init]) AC_LINK_IFELSE([AC_LANG_PROGRAM([],[ call MPI_Init])],[MPILIBS=" " AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)])]) fi AC_LANG_CASE([Fortran 77], [ if test x = x"$MPILIBS"; then AC_CHECK_LIB(fmpi, MPI_Init, [MPILIBS="-lfmpi"]) fi if test x = x"$MPILIBS"; then AC_CHECK_LIB(fmpich, MPI_Init, [MPILIBS="-lfmpich"]) fi if test x = x"$MPILIBS"; then AC_CHECK_LIB(mpif77, MPI_Init, [MPILIBS="-lmpif77"]) fi ], [Fortran], [ if test x = x"$MPILIBS"; then AC_CHECK_LIB(fmpi, MPI_Init, [MPILIBS="-lfmpi"]) fi if test x = x"$MPILIBS"; then AC_CHECK_LIB(mpichf90, MPI_Init, [MPILIBS="-lmpichf90"]) fi ]) if test x = x"$MPILIBS"; then AC_CHECK_LIB(mpi, MPI_Init, [MPILIBS="-lmpi"]) fi if test x = x"$MPILIBS"; then AC_CHECK_LIB(mpich, MPI_Init, [MPILIBS="-lmpich"]) fi dnl We have to use AC_TRY_COMPILE and not AC_CHECK_HEADER because the dnl latter uses $CPP, not $CC (which may be mpicc). AC_LANG_CASE([C], [if test x != x"$MPILIBS"; then AC_MSG_CHECKING([for mpi.h]) AC_TRY_COMPILE([#include ],[],[AC_MSG_RESULT(yes)], [MPILIBS="" AC_MSG_RESULT(no)]) fi], [C++], [if test x != x"$MPILIBS"; then AC_MSG_CHECKING([for mpi.h]) AC_TRY_COMPILE([#include ],[],[AC_MSG_RESULT(yes)], [MPILIBS="" AC_MSG_RESULT(no)]) fi], [Fortran 77], [if test x != x"$MPILIBS"; then AC_MSG_CHECKING([for mpif.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[ include 'mpif.h'])],[AC_MSG_RESULT(yes)], [MPILIBS="" AC_MSG_RESULT(no)]) fi], [Fortran], [if test x != x"$MPILIBS"; then AC_MSG_CHECKING([for mpif.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[ include 'mpif.h'])],[AC_MSG_RESULT(yes)], [MPILIBS="" AC_MSG_RESULT(no)]) fi]) AC_LANG_CASE([C], [CC="$ax_mpi_save_CC"], [C++], [CXX="$ax_mpi_save_CXX"], [Fortran 77], [F77="$ax_mpi_save_F77"], [Fortran], [FC="$ax_mpi_save_FC"]) AC_SUBST(MPILIBS) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x = x"$MPILIBS"; then $2 : else ifelse([$1],,[AC_DEFINE(HAVE_MPI,1,[Define if you have the MPI library.])],[$1]) : fi ])dnl AX_MPI