!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer,
! version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer
!version 3 or (at your option) any later version that should be found at:
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html
!
!This software 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 above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software;
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec),
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
!
subroutine hesseigen(n,nev,ncv,Eval,v,tol) 1,2
#if defined (DOC)
*
***s/r hesseigen - Driver for ARPACK solver to calculate hessian eigen vectors
*
*Author : M. Buehner June, 2002
*Revision : S. Pellerin, January 2009
* .Call to new simulator (simvar)
c-----------------------------------------------------------------------
c SUBROUTINE: HESSEIGEN
c Driver subroutine for calling Lanczos algorithm to calculate
c Hessian eigenvectors
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 avhess 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 avhess.
c n - dimension of space
c nev - number of modes to compute
c ncv - twice (or thrice) the number of modes (for internal workspace)
c-----------------------------------------------------------------------
#endif
c
c Arguments
#include "comlun.cdk"
Integer n,nev,ncv
Real*8 v(n,ncv), Eval(nev)
Real*8 tol
c
c | Local Arrays |
Real*8 workl(ncv*(ncv+8)),workd(3*n),
& d(ncv,2), resid(n),ax(n)
logical select(ncv)
c
POINTER (PTworkl,workl)
POINTER (PTworkd,workd)
POINTER (PTd,d)
POINTER (PTresid,resid)
POINTER (PTax,ax)
POINTER (PTselect,select)
c
integer iparam(11), ipntr(11)
c
c | Local Scalars |
character bmat*1, which*2
integer ido, lworkl, info, ierr, j,
& nconv, maxitr, mode, ishfts
logical rvec
Real*8
& sigma
c | Parameters |
Real*8
& zero
parameter (zero = 0.0E+0)
c | BLAS & LAPACK routines used |
Real*8
& dnrm2
external dnrm2, daxpy
c | Intrinsic function |
intrinsic dabs
c
c Allocate local arrays
c
ilen = ncv*(ncv+8)
CALL HPALLOC(PTworkl ,MAX(ILEN,1),IERR,8)
ilen = 3*n
CALL HPALLOC(PTworkd ,MAX(ILEN,1),IERR,8)
ilen = 2*ncv
CALL HPALLOC(PTd ,MAX(ILEN,1),IERR,8)
ilen = n
CALL HPALLOC(PTresid ,MAX(ILEN,1),IERR,8)
ilen = n
CALL HPALLOC(PTax ,MAX(ILEN,1),IERR,8)
ilen = ncv
CALL HPALLOC(PTselect ,MAX(ILEN,1),IERR,8)
c
write(nulout,*) 'STARTING SSDRVTEST'
bmat = 'I'
which = 'LM'
c
lworkl = ncv*(ncv+8)
c tol = zero
info = 0
ido = 0
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
c write(nulout,*) 'CALLING SSAUPD'
call dsaupd ( ido, bmat, n, which, nev, tol, resid,
& ncv, v, n, iparam, ipntr, workd, workl,
& lworkl, info )
c
if (ido .eq. -1 .or. ido .eq. 1) then
c
call avhess
(n, workd(ipntr(1)), workd(ipntr(2)))
c
go to 10
c
end if
c
c write(nulout,*) 'finished looping on ssaupd'
if ( info .lt. 0 ) then
c
write(nulout,*) ' '
write(nulout,*) ' Error with _saupd, info = ', info
write(nulout,*) ' Check documentation in _saupd '
write(nulout,*) ' '
c
else
c
rvec = .true.
c
call dseupd ( rvec, 'All', select, d, v, n, sigma,
& bmat, n, which, nev, tol, resid, ncv, v, n,
& 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. |
c
if ( ierr .ne. 0) then
c
write(nulout,*) ' '
write(nulout,*) ' Error with _seupd, info = ', ierr
write(nulout,*) ' Check the documentation of _seupd. '
write(nulout,*) ' '
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 avhess
(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) / dabs(d(j,1))
c
20 continue
c
call dmout(6, nconv, 2, d, ncv, -6,
& 'Ritz values and relative residuals')
end if
c
if ( info .eq. 1) then
write(nulout,*) ' '
write(nulout,*) ' Maximum number of iterations reached.'
write(nulout,*) ' '
else if ( info .eq. 3) then
write(nulout,*) ' '
write(nulout,*) ' No shifts could be applied during implicit',
& ' Arnoldi update, try increasing NCV.'
write(nulout,*) ' '
end if
c
write(nulout,*) ' '
write(nulout,*) ' _SDRV1 '
write(nulout,*) ' ====== '
write(nulout,*) ' '
write(nulout,*) ' Size of the matrix is ', n
write(nulout,*) ' The number of Ritz values requested is ', nev
write(nulout,*) ' The number of Arnoldi vectors generated',
& ' (NCV) is ', ncv
write(nulout,*) ' What portion of the spectrum: ', which
write(nulout,*) ' The number of converged Ritz values is ',
& nconv
write(nulout,*) ' The number of Implicit Arnoldi update',
& ' iterations taken is ', iparam(3)
write(nulout,*) ' The number of OP*x is ', iparam(9)
write(nulout,*) ' The convergence criterion is ', tol
write(nulout,*) ' '
do j=1,nev
Eval(j)=d(j,1)
enddo
c
end if
c
9000 continue
c
c Deallocate local arrays
c
CALL HPDEALLC(PTworkl ,IERR,1)
CALL HPDEALLC(PTworkd ,IERR,1)
CALL HPDEALLC(PTd ,IERR,1)
CALL HPDEALLC(PTresid ,IERR,1)
CALL HPDEALLC(PTax ,IERR,1)
CALL HPDEALLC(PTselect ,IERR,1)
c
end
c
c ------------------------------------------------------------------
c matrix vector subroutine
c
c Computes w <--- OP*v, where OP is the Hessian of Jo in space of
c control vector
c ------------------------------------------------------------------
subroutine avhess (n, v, w) 2,2
IMPLICIT NONE
#include "comdim.cdk"
#include "comlun.cdk"
#include "comcva.cdk"
#include "comvarqc.cdk"
c
integer n, j, i, indic, iprecon
INTEGER JN,JM,ILA,JK
LOGICAL LVQC
Real*8
& v(n), w(n), zjsp
c
INDIC = 3
DO i=1,NVADIM
VAZG(i) = 0.0
VAZX(i) = V(i)
ENDDO
LVQC=LVARQC
LVARQC=.false.
iprecon=nprecon
nprecon=0
write(nulout,*) 'CALLING simvar'
call vflush
(nulout)
call simvar
(indic,nvadim,vazx,zjsp,vazg)
nprecon=iprecon
LVARQC=LVQC
DO i=1,N
W(i)=0.0
ENDDO
DO i=1,NVADIM
W(i)=VAZG(i)
ENDDO
c
return
end