109 logical :: created = .false.
151 character(10) :: name
156 real(RP),
dimension(:),
allocatable ::
lambda 159 real(RP),
dimension(:,:),
allocatable :: v
251 eig%created = .false.
269 integer,
intent(in) :: size, nev
270 logical,
intent(in) :: sym, std
273 &
"eigen_mod : eigen_create" 276 if (size<=0)
call quit(&
277 &
"eigen_mod: eigen_create: 'size' <= 0")
280 if ((nev<=0).OR.(nev>size))
call quit(&
281 &
"eigen_mod: eigen_create: wrong argument 'nev'")
323 subroutine eigen_set(eig, type, mode, which, tol, itMax, &
326 integer ,
intent(in),
optional ::
type, mode, itMax, verb, which
327 real(RP),
intent(in),
optional :: tol, shift
329 if (.NOT.eig%created)
call quit(
"eigen_mod: eigen_set:& 330 & not created, 'eig=eigen()' missing")
333 &
"eigen_mod : eigen_set" 335 if(
present(
type )) eig%type =
type 336 if(
present(mode )) eig%mode = mode
337 if(
present(tol )) eig%tol = tol
338 if(
present(itmax)) eig%itMax = itmax
339 if(
present(shift)) eig%shift = shift
340 if(
present(verb )) eig%verb = verb
341 if(
present(which)) eig%which = which
344 if(
present(which))
then 345 select case(eig%which)
348 call quit(
"eigen_mod: eigen_set: 'which' = uncorrect")
353 if (
present(type))
then 354 select case(eig%type)
358 call quit(
"eigen_mod: eigen_set: 'type' = uncorrect")
363 if (
present(mode))
then 367 call quit(
"eigen_mod: eigen_set: 'mode' = uncorrect")
372 if (
present(tol))
then 373 if (tol<=0.0_rp)
call quit(&
374 &
"eigen_mod: eigen_set: 'tol' <= 0")
378 if (
present(itmax))
then 379 if (itmax<=0)
call quit(&
380 &
"eigen_mod: eigen_set: 'itMax' <= 0")
391 write(*,*)
"eigen_mod : eigen_print" 392 write(*,*)
" Created =", eig%created
393 if (.NOT.eig%created)
return 394 if (eig%standard)
then 395 write(*,*)
" Standard eigenproblem" 397 write(*,*)
" Generalised eigenproblem" 399 if (eig%symmetric)
then 400 write(*,*)
" Symmetric case" 402 write(*,*)
" Non symmetric case" 404 write(*,*)
" Solver Name = ", trim(eig%name)
405 select case(eig%mode)
407 write(*,*)
" Mode = regular" 409 write(*,*)
" Mode = inverse" 411 write(*,*)
" Mode = shift-invert" 412 write(*,*)
" Shift factor =", eig%shift
414 write(*,*)
" Mode = undefined" 416 select case(eig%which)
418 write(*,*)
" Which eigenvalues = smallest magnitude" 420 write(*,*)
" Which eigenvalues = largest magnitude" 422 write(*,*)
" Wich eigenvalues = undefined" 424 write(*,*)
" Number of eigenvalues/vectors =", eig%nev
425 write(*,*)
" Problem size =", eig%size
426 write(*,*)
" Tolerance =", eig%tol
427 write(*,*)
" ItMax =", eig%itMax
428 write(*,*)
" Verbosity =", eig%verb
459 procedure(rntorn) ,
optional :: A, B
460 procedure(rntornxl),
optional :: Op
464 if (.NOT.eig%created)
call quit(&
465 &
"eigen: mode: eigen_solve: 'eig' not created yet,& 466 & try 'eig = eigen(...)' first")
468 if ( (eig%nev <= 0) .OR. (eig%nev > eig%size) )
call quit(&
469 &
"eigen: mode: eigen_solve: wrong eig%nev =& 470 & number of eigenvalues to be computed")
473 if (eig%verb>0)
write(*,*)
"eigen_mod :& 474 & eigen_solve = ", trim(eig%name)
478 if (eig%standard)
then 480 if (eig%verb>1)
write(*,*)
"eigen_mod :& 481 & eigen_solve = standard eigen-problem" 483 if (
present(b))
call quit(&
484 &
"eigen_mod: eigen_solve:& 485 & standard eigen-problem: unconsistent arg 'B'")
487 select case(eig%mode)
490 if (eig%verb>1)
write(*,*)
"eigen_mod :& 491 & eigen_solve = regular mode" 493 if (.NOT.
present(a))
call quit(&
494 &
"eigen_mod: eigen_solve:& 495 & standard + EIG_REGULAR: operator 'A' missing")
496 if (
present(op))
call quit(&
497 &
"eigen_mod: eigen_solve:& 498 & standard + EIG_REGULAR: unconsistent arg 'Op'")
501 call quit(
"eigen_mod: eigen_solve:& 502 & standard + EIG_INVERSE not compatible")
505 if (eig%verb>1)
write(*,*)
"eigen_mod :& 506 & eigen_solve = shift-invert mode" 508 if (.NOT.
present(op))
call quit(&
509 &
"eigen_mod: eigen_solve:& 510 & standard + EIG_SHIFT_INVERT: arg 'Op' missing")
511 if (
present(a))
call quit(&
512 &
"eigen_mod: eigen_solve:& 513 & standard + EIG_SHIFT_INVERT: unconsistent arg 'A'")
519 if (eig%verb>1)
write(*,*)
"eigen_mod :& 520 & eigen_solve = generalised eigen-problem" 522 select case(eig%mode)
524 call quit(
"eigen_mod: eigen_solve:& 525 & generalised + EIG_REGULAR: not compatible")
528 if (eig%verb>1)
write(*,*)
"eigen_mod :& 529 & eigen_solve = inverse mode" 531 if (.NOT.
present(op))
call quit(&
532 &
"eigen_mod: eigen_solve:& 533 & generalised + EIG_INVERSE: operator 'Op' missing")
534 if (.NOT.
present(b))
call quit(&
535 &
"eigen_mod: eigen_solve:& 536 & generalised + EIG_INVERSE: operator 'B' missing")
537 if (.NOT.
present(a))
call quit(&
538 &
"eigen_mod: eigen_solve:& 539 & generalised + EIG_INVERSE: operator 'A' missing")
542 if (eig%verb>1)
write(*,*)
"eigen_mod :& 543 & eigen_solve = shift-invert mode" 544 if (.NOT.
present(op))
call quit(&
545 &
"eigen_mod: eigen_solve:& 546 & generalised + EIG_SHIFT_INVERT: operator 'Op' missing")
547 if (.NOT.
present(b))
call quit(&
548 &
"eigen_mod: eigen_solve:& 549 & generalised + EIG_SHIFT_INVERT: operator 'B' missing")
550 if (
present(a))
call quit(&
551 &
"eigen_mod: eigen_solve:& 552 & generalised + EIG_SHIFT_INVERT: unconsistent arg 'A'")
565 call allocmem(eig%v, eig%size, eig%nev)
567 select case(eig%type)
572 call quit(
"eigen_mod: solve_standard: set 'WITH_ARPACK=1' in the& 573 & file 'CONFIG.in', re-configure (ARPACK must be installed)")
579 if (eig%verb>1)
write(*,*)
"eigen_mod :& 580 & eigen_solve = finished" 581 write(*,*)
" Iterations =", eig%iter
582 if (eig%AEval>0)
then 583 write(*,*)
" Nb of mat-vec products x-->A*x =", eig%AEval
585 if (eig%BEval>0)
then 586 write(*,*)
" Nb of mat-vec products x-->B*x =", eig%BEval
588 if (eig%OpEval>0)
then 589 write(*,*)
" Nb of linear system inversions =", eig%OpEval
592 write(*,*)
' CPU =',
real(cpu,
sp)
593 select case(eig%ierr)
595 write(*,*)
" Converged" 597 write(*,*)
" Not converged, ierr =", eig%ierr
615 procedure(rntorn) ,
optional :: A, B
616 procedure(rntornxl),
optional :: Op
621 & arpack_solve: double precision only")
623 if (eig%symmetric)
then 624 if (eig%verb>1)
write(*,*)
"eigen_mod :& 625 & arpack_solve = symmetric" 628 call quit(
"eigen_mod: arpack_solve:& 629 & non-symmetric case not implemented")
639 procedure(rntorn) ,
optional :: A, B
640 procedure(rntornxl),
optional :: Op
642 real(RP),
dimension(:) ,
allocatable :: resid, workd, workl
643 real(RP),
dimension(:,:),
allocatable :: v
644 integer,
dimension(11) :: iParam, iPntr
645 integer :: ncv, lworkl
647 integer :: i1, i2, j1, j2
648 character(2) :: which
651 logical :: rVec, op_err
652 logical,
dimension(:),
allocatable :: select
657 select case(eig%which)
667 call quit(
"eigen_mod: arpack_ds: 'eig%which' = unknown")
672 select case(eig%mode)
683 call quit(
"eigen_mod: arpack_ds: 'eig%mode' = unknown")
688 if (.NOT.eig%standard)
then 695 if (ncv > eig%size) ncv = eig%size
697 iparam(3) = eig%itMax
716 solve_loop:
do while(.true.)
718 call dsaupd( ido, bmat, eig%size, which, eig%nev, eig%tol, resid,&
719 & ncv, v, eig%size, iparam, ipntr, workd, workl,&
727 write(*,*)
" info (see ARPACK 'dsaupd' doc) =", info
728 call quit(
"eigen_mod: arpack_ds:& 729 & ARPACK 'dsaupd' error:,& 730 & info < 0, check parameters")
732 else if (info == 1)
then 733 if (eig%verb>0)
write(*,*)
" maximum number of iterations reached" 734 call warning(
"eigen_mod: arpack_ds:& 735 & 'dsaupd' not converges", eig%verb)
739 else if (info > 1 )
then 740 write(*,*)
" info (see ARPACK 'dsaupd' doc) =", info
741 call quit(
"eigen_mod: arpack_ds:& 742 & ARPACK 'dsaupd' error")
748 if (ido .eq. -1 .or. ido .eq. 1)
then 750 if (eig%standard)
then 755 j1 = i1 + eig%size -1
756 j2 = i2 + eig%size -1
758 select case(eig%mode)
761 call a(workd(i2:j2), workd(i1:j1))
762 eig%AEval = eig%AEval + 1
766 call op(workd(i2:j2), op_err, workd(i1:j1))
767 eig%OpEval = eig%OpEval + 1
769 &
"eigen_mod: arpack_ds:& 770 & check operation 'y = Op x' ", eig%verb-1)
776 select case(eig%mode)
781 j1 = i1 + eig%size -1
782 j2 = i2 + eig%size -1
784 call a(workd(i2:j2), workd(i1:j1))
785 eig%AEval = eig%AEval + 1
786 workd(i1:j1) = workd(i2:j2)
788 call op(workd(i2:j2), op_err, workd(i1:j1))
789 eig%OpEval = eig%OpEval + 1
791 &
"eigen_mod: arpack_ds:& 792 & check operation 'y = Op x' ", eig%verb-1)
795 if (ido .eq. -1 )
then 800 j1 = i1 + eig%size -1
801 j2 = i2 + eig%size -1
803 call b(workd(i2:j2), workd(i1:j1))
804 eig%BEval = eig%BEval + 1
805 workd(i1:j1) = workd(i2:j2)
807 call op(workd(i2:j2), op_err, workd(i1:j1))
808 eig%OpEval = eig%OpEval + 1
810 &
"eigen_mod: arpack_ds:& 811 & check operation 'y = Op x' ", eig%verb-1)
818 j1 = i1 + eig%size -1
819 j2 = i2 + eig%size -1
821 call op(workd(i2:j2), op_err, workd(i1:j1))
822 eig%OpEval = eig%OpEval + 1
824 &
"eigen_mod: arpack_ds:& 825 & check operation 'y = Op x' ", eig%verb-1)
833 else if (ido == 2)
then 838 j1 = i1 + eig%size -1
839 j2 = i2 + eig%size -1
841 call b(workd(i2:j2), workd(i1:j1))
842 eig%BEval = eig%BEval + 1
844 else if (ido == 99)
then 848 write(*,*)
" ido (see ARPACK 'dsaupd' doc) =", ido
849 call quit(
"eigen_mod: arpack_ds:& 850 & ARPACK 'dsaupd' error")
862 if (iparam(5) < eig%nev)
then 863 if (eig%verb>0)
write(*,*) &
864 &
" numer of converged eigen modes =", iparam(5)
865 call warning(
"eigen_mod: arpack_ds:& 866 & not converged", eig%verb)
874 call dseupd ( .true.,
'A',
select, eig%lambda, v, eig%size, &
875 & eig%shift, bmat, eig%size, which, eig%nev, &
876 & eig%tol, resid, ncv, v, eig%size, &
877 & iparam, ipntr, workd, workl, lworkl, info )
879 if ( info .ne. 0)
then 880 write(*,*)
" info (see dseupd arpack doc) =", info
881 call quit(
"eigen_mod: arpack_ds:& 882 & ARPACK 'dseupd' error")
888 eig%v(1:eig%size,1:eig%nev) = v(1:eig%size, 1:eig%nev)
DEFINITION OF ABSTRACT_INTERFACES FOR THE LIBRARY CHORAL
integer, parameter eig_shift_invert
Shift-invert mode.
DERIVED TYPE eigen for eigenvalue / eigenvector problems
deallocate memory for real(RP) arrays
integer, parameter eig_regular
Regual Mode.
subroutine arpack_ds(eig, A, B, Op)
ARPACK, symmetric case.
subroutine arpack_solve(eig, A, B, Op)
integer, parameter, public rp
real(kind=RP) = real precision in the code REAL_TOL = epsilon to test real equality ...
integer, parameter, public sp
simple precision for real numbers
integer, parameter eig_which_lm
Computation of eigenvalues xith largest magnitude.
REAL NUMBERS PRECISION IN CHORAL: selects simple/double/quad
print a short description
real(rp) function e(x, v1, v2)
integer, parameter eig_arpack
allocate memory for real(RP) arrays
Derived type for eigenvalue problem resolution.
integer, parameter eig_inverse
Inverse mode.
subroutine eigen_print(eig)
Print a short description.
integer choral_verb
Verbosity level.
integer, parameter eig_which_sm
Computation of eigenvalues xith smallest magnitude.
subroutine eigen_set(eig, type, mode, which, tol, itMax, shift, verb)
Eigen-solver settings
integer, parameter, public dp
double precision for real numbers
subroutine eigen_solve(eig, A, B, Op)
Eigen-problem resolution
DEFINITION OF GLOBAL VARIABLES FOR THE LIBRARY CHORAL
type(eigen) function eigen_create(size, nev, sym, std)
constructor for the type eigen
real(rp) function lambda(x)
Lame coefficient 'lambda'.
subroutine eigen_clear(eig)
Destructor.