Choral
eigen_mod.F90
Go to the documentation of this file.
1 
72 
73 module eigen_mod
74 
76  use real_type
78  use abstract_interfaces, only: rntorn, rntornxl
79  use basic_tools
80 
81  implicit none
82  private
83 
84 
85 
86  ! %----------------------------------------%
87  ! | |
88  ! | PUBLIC DATA |
89  ! | |
90  ! %----------------------------------------%
91  !! TYPE
92  public :: eigen
93 
94  !! GENERIC SUBROUTINES
95  public :: clear
96  public :: set, solve
97  public :: print
98 
99 
100  ! %----------------------------------------%
101  ! | |
102  ! | DERIVED TYPE |
103  ! | |
104  ! %----------------------------------------%
106  type eigen
107 
109  logical :: created = .false.
110 
111  !! parameters provided by the constructor 'eig = eigen(...)'
112  !!
114  integer :: size
115 
117  integer :: nev
118 
120  logical :: standard
121 
123  logical :: symmetric
124 
126  integer :: mode
127 
129  integer :: which
130 
131  !! parameters provided by 'call set(eig, ...)'
132  !!
134  integer :: type
135 
137  real(RP) :: tol
138 
140  integer :: itmax
141 
143  real(RP) :: shift
144 
146  integer :: verb
147 
148  !! Parameter defined by the code with 'call set(eig, ...)'
149  !!
151  character(10) :: name
152 
153  !! Data computed with 'call solve(eig, ...)'
154  !!
156  real(RP), dimension(:), allocatable :: lambda
157 
159  real(RP), dimension(:,:), allocatable :: v
160 
161  !! Parameter returned by the code after solving
162  !!
164  integer :: iter
166  integer :: aeval
168  integer :: beval
170  integer :: opeval
172  integer :: ierr
173 
174  contains
175  final :: eigen_clear
176  end type eigen
177 
178  ! %----------------------------------------%
179  ! | |
180  ! | GENERIC INTERFACES |
181  ! | |
182  ! %----------------------------------------%
184  interface print
185  module procedure eigen_print
186  end interface print
187 
189  interface clear
190  module procedure eigen_clear
191  end interface clear
192 
193  !! constructor
194  interface eigen
195  module procedure eigen_create
196  end interface eigen
197 
199  interface set
200  module procedure eigen_set
201  end interface set
202 
239  interface solve
240  module procedure eigen_solve
241  end interface solve
242 
243 contains
244 
245 
248  subroutine eigen_clear(eig)
249  type(eigen), intent(inout) :: eig
250 
251  eig%created = .false.
252  call freemem(eig%lambda)
253  call freemem(eig%v)
254 
255  end subroutine eigen_clear
256 
267  function eigen_create(size, nev, sym, std) result(eig)
268  type(eigen) :: eig
269  integer, intent(in) :: size, nev
270  logical, intent(in) :: sym, std
271 
272  if (choral_verb>1) write(*,*) &
273  & "eigen_mod : eigen_create"
274 
275  !! checking size
276  if (size<=0) call quit(&
277  & "eigen_mod: eigen_create: 'size' <= 0")
278 
279  !! checking nev
280  if ((nev<=0).OR.(nev>size)) call quit(&
281  & "eigen_mod: eigen_create: wrong argument 'nev'")
282 
283  call clear(eig)
284 
285  eig%size = size
286  eig%nev = nev
287  eig%symmetric = sym
288  eig%standard = std
289 
290  ! set parameters to default ones
291  eig%type = eig_arpack
292  eig%mode = eig_regular
293  eig%shift = 0.0_rp
294  eig%tol = 1e-8_rp
295  eig%itMax = 100
296  eig%verb = 0
297  eig%name = 'ARPACK'
298  eig%which = eig_which_sm
299 
300  eig%created = .true.
301 
302  end function eigen_create
303 
304 
323  subroutine eigen_set(eig, type, mode, which, tol, itMax, &
324  & shift, verb)
325  type(eigen) , intent(inout) :: eig
326  integer , intent(in), optional :: type, mode, itMax, verb, which
327  real(RP), intent(in), optional :: tol, shift
328 
329  if (.NOT.eig%created) call quit("eigen_mod: eigen_set:&
330  & not created, 'eig=eigen()' missing")
331 
332  if (choral_verb>1) write(*,*) &
333  & "eigen_mod : eigen_set"
334 
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
342 
343  !! checking which
344  if(present(which)) then
345  select case(eig%which)
347  case default
348  call quit("eigen_mod: eigen_set: 'which' = uncorrect")
349  end select
350  end if
351 
352  !! checking type
353  if (present(type)) then
354  select case(eig%type)
355  case(eig_arpack)
356  eig%name = 'ARPACK'
357  case default
358  call quit("eigen_mod: eigen_set: 'type' = uncorrect")
359  end select
360  end if
361 
362  !! checking mode
363  if (present(mode)) then
364  select case(mode)
366  case default
367  call quit("eigen_mod: eigen_set: 'mode' = uncorrect")
368  end select
369  end if
370 
371  !! checking tol
372  if (present(tol)) then
373  if (tol<=0.0_rp) call quit(&
374  & "eigen_mod: eigen_set: 'tol' <= 0")
375  end if
376 
377  !! checking itMax
378  if (present(itmax)) then
379  if (itmax<=0) call quit(&
380  & "eigen_mod: eigen_set: 'itMax' <= 0")
381  end if
382 
383 
384  end subroutine eigen_set
385 
386 
388  subroutine eigen_print (eig)
389  type(eigen), intent(in) :: eig
390 
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"
396  else
397  write(*,*)" Generalised eigenproblem"
398  end if
399  if (eig%symmetric) then
400  write(*,*)" Symmetric case"
401  else
402  write(*,*)" Non symmetric case"
403  end if
404  write(*,*)" Solver Name = ", trim(eig%name)
405  select case(eig%mode)
406  case(eig_regular)
407  write(*,*)" Mode = regular"
408  case(eig_inverse)
409  write(*,*)" Mode = inverse"
410  case(eig_shift_invert)
411  write(*,*)" Mode = shift-invert"
412  write(*,*)" Shift factor =", eig%shift
413  case default
414  write(*,*)" Mode = undefined"
415  end select
416  select case(eig%which)
417  case(eig_which_sm)
418  write(*,*)" Which eigenvalues = smallest magnitude"
419  case(eig_which_lm)
420  write(*,*)" Which eigenvalues = largest magnitude"
421  case default
422  write(*,*)" Wich eigenvalues = undefined"
423  end select
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
429 
430  end subroutine eigen_print
431 
432 
433 
457  subroutine eigen_solve(eig, A, B, Op)
458  type(eigen), intent(inout) :: eig
459  procedure(rntorn) , optional :: A, B
460  procedure(rntornxl), optional :: Op
461 
462  real(DP) :: cpu
463 
464  if (.NOT.eig%created) call quit(&
465  & "eigen: mode: eigen_solve: 'eig' not created yet,&
466  & try 'eig = eigen(...)' first")
467 
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")
471 
472 
473  if (eig%verb>0) write(*,*)"eigen_mod :&
474  & eigen_solve = ", trim(eig%name)
475 
476  !! Check argument list
477  !!
478  if (eig%standard) then
479 
480  if (eig%verb>1) write(*,*) "eigen_mod :&
481  & eigen_solve = standard eigen-problem"
482 
483  if (present(b)) call quit(&
484  & "eigen_mod: eigen_solve:&
485  & standard eigen-problem: unconsistent arg 'B'")
486 
487  select case(eig%mode)
488  case(eig_regular)
489 
490  if (eig%verb>1) write(*,*) "eigen_mod :&
491  & eigen_solve = regular mode"
492 
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'")
499 
500  case(eig_inverse)
501  call quit("eigen_mod: eigen_solve:&
502  & standard + EIG_INVERSE not compatible")
503 
504  case(eig_shift_invert)
505  if (eig%verb>1) write(*,*) "eigen_mod :&
506  & eigen_solve = shift-invert mode"
507 
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'")
514 
515  end select
516 
517  else !! generalised problem
518 
519  if (eig%verb>1) write(*,*) "eigen_mod :&
520  & eigen_solve = generalised eigen-problem"
521 
522  select case(eig%mode)
523  case(eig_regular)
524  call quit("eigen_mod: eigen_solve:&
525  & generalised + EIG_REGULAR: not compatible")
526 
527  case(eig_inverse)
528  if (eig%verb>1) write(*,*) "eigen_mod :&
529  & eigen_solve = inverse mode"
530 
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")
540 
541  case(eig_shift_invert)
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'")
553 
554  end select
555  end if
556 
557 
558  !! initialise
559  cpu = clock()
560  eig%ierr = 0
561  eig%AEval = 0
562  eig%BEval = 0
563  eig%OpEval = 0
564  call allocmem(eig%lambda, eig%nev)
565  call allocmem(eig%v, eig%size, eig%nev)
566 
567  select case(eig%type)
568  case(eig_arpack)
569 #ifdef WARPACK
570  call arpack_solve(eig, a, b, op)
571 #else
572  call quit("eigen_mod: solve_standard: set 'WITH_ARPACK=1' in the&
573  & file 'CONFIG.in', re-configure (ARPACK must be installed)")
574 #endif
575  end select
576 
577  !! Display
578  if (eig%verb>1) then
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
584  end if
585  if (eig%BEval>0) then
586  write(*,*) " Nb of mat-vec products x-->B*x =", eig%BEval
587  end if
588  if (eig%OpEval>0) then
589  write(*,*) " Nb of linear system inversions =", eig%OpEval
590  end if
591  cpu = clock() - cpu
592  write(*,*) ' CPU =', real(cpu, sp)
593  select case(eig%ierr)
594  case(0)
595  write(*,*) " Converged"
596  case default
597  write(*,*) " Not converged, ierr =", eig%ierr
598  end select
599  end if
600 
601  end subroutine eigen_solve
602 
603 
604  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
605  !!
606  !! WRAPPER TO ARPACK
607  !!
608  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
609  !!
610 #ifdef WARPACK
611 
612 
613  subroutine arpack_solve(eig, A, B, Op)
614  type(eigen), intent(inout) :: eig
615  procedure(rntorn) , optional :: A, B
616  procedure(rntornxl), optional :: Op
617 
618  !! double precision only
619  !!
620  if (rp/=dp) call quit("eigen_mod:&
621  & arpack_solve: double precision only")
622 
623  if (eig%symmetric) then
624  if (eig%verb>1) write(*,*)"eigen_mod :&
625  & arpack_solve = symmetric"
626  call arpack_ds(eig, a, b, op)
627  else
628  call quit("eigen_mod: arpack_solve:&
629  & non-symmetric case not implemented")
630  end if
631 
632  end subroutine arpack_solve
633 
634 
637  subroutine arpack_ds(eig, A, B, Op)
638  type(eigen), intent(inout) :: eig
639  procedure(rntorn) , optional :: A, B
640  procedure(rntornxl), optional :: Op
641 
642  real(RP), dimension(:) , allocatable :: resid, workd, workl
643  real(RP), dimension(:,:), allocatable :: v
644  integer, dimension(11) :: iParam, iPntr
645  integer :: ncv, lworkl
646  integer :: info, ido
647  integer :: i1, i2, j1, j2
648  character(2) :: which
649  character(1) :: bMat
650 
651  logical :: rVec, op_err
652  logical, dimension(:), allocatable :: select
653 
654 
655  !! which = part of the spectrum to be computed
656  !!
657  select case(eig%which)
658  case(eig_which_sm)
659  which = 'SM'
660  if (eig%mode==eig_shift_invert) which = 'LM'
661 
662  case(eig_which_lm)
663  which = 'LM'
664  if (eig%mode==eig_shift_invert) which = 'SM'
665 
666  case default
667  call quit("eigen_mod: arpack_ds: 'eig%which' = unknown")
668  end select
669 
670  !! mode
671  !!
672  select case(eig%mode)
673  case(eig_regular)
674  iparam(7) = 1
675 
676  case(eig_inverse)
677  iparam(7) = 2
678 
679  case(eig_shift_invert)
680  iparam(7) = 3
681 
682  case default
683  call quit("eigen_mod: arpack_ds: 'eig%mode' = unknown")
684  end select
685 
686  !! standard / generalised problem
687  bmat = 'I'
688  if (.NOT.eig%standard) then
689  bmat = 'G'
690  end if
691 
692  !! INITIALISATION
693  !!
694  ncv = 2*eig%nev + 1 ! size for v
695  if (ncv > eig%size) ncv = eig%size
696  iparam(1) = 1 ! ishifts = 1
697  iparam(3) = eig%itMax ! Max iter number
698  iparam(4) = 1 ! ???
699  lworkl = ncv*(ncv+8)
700  call allocmem(workl, lworkl)
701  call allocmem(resid, eig%size)
702  call allocmem(workd, 3*eig%size)
703  call allocmem(v, eig%size, ncv)
704  !!
705  resid = 0.0_rp
706  workl = 0.0_rp
707  workd = 0.0_rp
708  v = 0.0_rp
709 
710  !! ARPACK EIGEN-MODE COMPUTATION LOOP
711  !!
712  info = 0
713  resid = 0.0_rp
714  ido = 0
715  !!
716  solve_loop: do while(.true.)
717 
718  call dsaupd( ido, bmat, eig%size, which, eig%nev, eig%tol, resid,&
719  & ncv, v, eig%size, iparam, ipntr, workd, workl,&
720  & lworkl, info )
721 
722  !! Checks the output parameter 'info'
723  !! that must be equal to 0
724  !!
725  if (info /= 0) then
726  if (info < 0 ) then
727  write(*,*) " info (see ARPACK 'dsaupd' doc) =", info
728  call quit("eigen_mod: arpack_ds:&
729  & ARPACK 'dsaupd' error:,&
730  & info < 0, check parameters")
731 
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)
736  eig%ierr = 1
737  exit solve_loop
738 
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")
743  end if
744  end if
745 
746  !! Checks the output parameter 'ido'
747  !!
748  if (ido .eq. -1 .or. ido .eq. 1) then
749 
750  if (eig%standard) then
751 
752  i1 = ipntr(1)
753  i2 = ipntr(2)
754 
755  j1 = i1 + eig%size -1
756  j2 = i2 + eig%size -1
757 
758  select case(eig%mode)
759  case(eig_regular)
760 
761  call a(workd(i2:j2), workd(i1:j1))
762  eig%AEval = eig%AEval + 1
763 
764  case(eig_shift_invert)
765 
766  call op(workd(i2:j2), op_err, workd(i1:j1))
767  eig%OpEval = eig%OpEval + 1
768  if (op_err) call warning(&
769  & "eigen_mod: arpack_ds:&
770  & check operation 'y = Op x' ", eig%verb-1)
771 
772  end select
773 
774  else !! GENERALISED EIGENPROBLEM
775 
776  select case(eig%mode)
777  case(eig_inverse)
778  i1 = ipntr(1)
779  i2 = ipntr(2)
780 
781  j1 = i1 + eig%size -1
782  j2 = i2 + eig%size -1
783 
784  call a(workd(i2:j2), workd(i1:j1))
785  eig%AEval = eig%AEval + 1
786  workd(i1:j1) = workd(i2:j2)
787 
788  call op(workd(i2:j2), op_err, workd(i1:j1))
789  eig%OpEval = eig%OpEval + 1
790  if (op_err) call warning(&
791  & "eigen_mod: arpack_ds:&
792  & check operation 'y = Op x' ", eig%verb-1)
793 
794  case(eig_shift_invert)
795  if (ido .eq. -1 ) then
796 
797  i1 = ipntr(1)
798  i2 = ipntr(2)
799 
800  j1 = i1 + eig%size -1
801  j2 = i2 + eig%size -1
802 
803  call b(workd(i2:j2), workd(i1:j1))
804  eig%BEval = eig%BEval + 1
805  workd(i1:j1) = workd(i2:j2)
806 
807  call op(workd(i2:j2), op_err, workd(i1:j1))
808  eig%OpEval = eig%OpEval + 1
809  if (op_err) call warning(&
810  & "eigen_mod: arpack_ds:&
811  & check operation 'y = Op x' ", eig%verb-1)
812 
813  else !! ido = 1 here
814 
815  i1 = ipntr(3)
816  i2 = ipntr(2)
817 
818  j1 = i1 + eig%size -1
819  j2 = i2 + eig%size -1
820 
821  call op(workd(i2:j2), op_err, workd(i1:j1))
822  eig%OpEval = eig%OpEval + 1
823  if (op_err) call warning(&
824  & "eigen_mod: arpack_ds:&
825  & check operation 'y = Op x' ", eig%verb-1)
826 
827  end if
828 
829  end select
830 
831  end if
832 
833  else if (ido == 2) then
834 
835  i1 = ipntr(1)
836  i2 = ipntr(2)
837 
838  j1 = i1 + eig%size -1
839  j2 = i2 + eig%size -1
840 
841  call b(workd(i2:j2), workd(i1:j1))
842  eig%BEval = eig%BEval + 1
843 
844  else if (ido == 99) then
845  exit solve_loop
846 
847  else
848  write(*,*) " ido (see ARPACK 'dsaupd' doc) =", ido
849  call quit("eigen_mod: arpack_ds:&
850  & ARPACK 'dsaupd' error")
851 
852  end if
853 
854  end do solve_loop
855 
856  !! retrieve the number of performed Arnoldi's iterations
857  !!
858  eig%iter = iparam(3)
859 
860  !! check convergence
861  !!
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)
867  eig%ierr = 1
868  end if
869 
870  !! POST-PROCESSING
871  !!
872  rvec = .true.
873  call allocmem(select, ncv)
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 )
878 
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")
883 
884  end if
885 
886  !! RETRIEVE THE EIGEN-VECTORS
887  !!
888  eig%v(1:eig%size,1:eig%nev) = v(1:eig%size, 1:eig%nev)
889 
890  end subroutine arpack_ds
891 
892 
893 #endif
894 
895 end module eigen_mod
896 
DEFINITION OF ABSTRACT_INTERFACES FOR THE LIBRARY CHORAL
integer, parameter eig_shift_invert
Shift-invert mode.
BASIC TOOLS
Definition: basic_tools.F90:8
DERIVED TYPE eigen for eigenvalue / eigenvector problems
Definition: eigen_mod.F90:73
deallocate memory for real(RP) arrays
Definition: real_type.F90:163
double precision function, public clock()
Returns the internal clock time
Definition: basic_tools.F90:94
integer, parameter eig_regular
Regual Mode.
subroutine arpack_ds(eig, A, B, Op)
ARPACK, symmetric case.
Definition: eigen_mod.F90:638
subroutine arpack_solve(eig, A, B, Op)
Definition: eigen_mod.F90:614
integer, parameter, public rp
real(kind=RP) = real precision in the code REAL_TOL = epsilon to test real equality ...
Definition: real_type.F90:90
subroutine, public quit(message)
Stop program execution, display an error messahe.
integer, parameter, public sp
simple precision for real numbers
Definition: real_type.F90:60
integer, parameter eig_which_lm
Computation of eigenvalues xith largest magnitude.
REAL NUMBERS PRECISION IN CHORAL: selects simple/double/quad
Definition: real_type.F90:33
print a short description
Definition: eigen_mod.F90:184
real(rp) function e(x, v1, v2)
CHORAL CONSTANTS
integer, parameter eig_arpack
allocate memory for real(RP) arrays
Definition: real_type.F90:158
Derived type for eigenvalue problem resolution.
Definition: eigen_mod.F90:106
integer, parameter eig_inverse
Inverse mode.
subroutine eigen_print(eig)
Print a short description.
Definition: eigen_mod.F90:389
Solver for:
Definition: eigen_mod.F90:239
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
Definition: eigen_mod.F90:325
integer, parameter, public dp
double precision for real numbers
Definition: real_type.F90:63
set the solver
Definition: eigen_mod.F90:199
subroutine eigen_solve(eig, A, B, Op)
Eigen-problem resolution
Definition: eigen_mod.F90:458
DEFINITION OF GLOBAL VARIABLES FOR THE LIBRARY CHORAL
type(eigen) function eigen_create(size, nev, sym, std)
constructor for the type eigen
Definition: eigen_mod.F90:268
real(rp) function lambda(x)
Lame coefficient &#39;lambda&#39;.
subroutine, public warning(message, verb)
Warning message.
destructor
Definition: eigen_mod.F90:189
subroutine eigen_clear(eig)
Destructor.
Definition: eigen_mod.F90:249