eigen.F90 Source File


This file depends on

sourcefile~~eigen.f90~~EfferentGraph sourcefile~eigen.f90 eigen.F90 sourcefile~mathlib_types.f90 mathlib_types.F90 sourcefile~eigen.f90->sourcefile~mathlib_types.f90 sourcefile~messages.f90 messages.F90 sourcefile~eigen.f90->sourcefile~messages.f90 sourcefile~oqp_linalg.f90 oqp_linalg.F90 sourcefile~eigen.f90->sourcefile~oqp_linalg.f90 sourcefile~precision.f90 precision.F90 sourcefile~eigen.f90->sourcefile~precision.f90 sourcefile~messages.f90->sourcefile~precision.f90 sourcefile~constants_io.f90 constants_io.F90 sourcefile~messages.f90->sourcefile~constants_io.f90 sourcefile~blas_wrap.f90 blas_wrap.F90 sourcefile~oqp_linalg.f90->sourcefile~blas_wrap.f90 sourcefile~lapack_wrap.f90 lapack_wrap.F90 sourcefile~oqp_linalg.f90->sourcefile~lapack_wrap.f90 sourcefile~blas_wrap.f90->sourcefile~mathlib_types.f90 sourcefile~blas_wrap.f90->sourcefile~messages.f90 sourcefile~blas_wrap.f90->sourcefile~precision.f90 sourcefile~lapack_wrap.f90->sourcefile~mathlib_types.f90 sourcefile~lapack_wrap.f90->sourcefile~messages.f90 sourcefile~lapack_wrap.f90->sourcefile~precision.f90

Files dependent on this one

sourcefile~~eigen.f90~~AfferentGraph sourcefile~eigen.f90 eigen.F90 sourcefile~guess.f90 guess.F90 sourcefile~guess.f90->sourcefile~eigen.f90 sourcefile~mathlib.f90 mathlib.F90 sourcefile~guess.f90->sourcefile~mathlib.f90 sourcefile~huckel.f90 huckel.F90 sourcefile~huckel.f90->sourcefile~eigen.f90 sourcefile~huckel.f90->sourcefile~guess.f90 sourcefile~huckel.f90->sourcefile~mathlib.f90 sourcefile~mathlib.f90->sourcefile~eigen.f90 sourcefile~population_analysis.f90 population_analysis.F90 sourcefile~population_analysis.f90->sourcefile~eigen.f90 sourcefile~population_analysis.f90->sourcefile~mathlib.f90 sourcefile~tdhf_lib.f90 tdhf_lib.F90 sourcefile~tdhf_lib.f90->sourcefile~eigen.f90 sourcefile~tdhf_lib.f90->sourcefile~mathlib.f90 sourcefile~dft.f90 dft.F90 sourcefile~dft.f90->sourcefile~mathlib.f90 sourcefile~dft_gridint_fxc.f90 dft_gridint_fxc.F90 sourcefile~dft_gridint_fxc.f90->sourcefile~mathlib.f90 sourcefile~dft_gridint_gxc.f90 dft_gridint_gxc.F90 sourcefile~dft_gridint_gxc.f90->sourcefile~mathlib.f90 sourcefile~dft_gridint_gxc.f90->sourcefile~dft_gridint_fxc.f90 sourcefile~electric_moments.f90 electric_moments.F90 sourcefile~electric_moments.f90->sourcefile~mathlib.f90 sourcefile~grd1.f90 grd1.F90 sourcefile~grd1.f90->sourcefile~mathlib.f90 sourcefile~guess_hcore.f90 guess_hcore.F90 sourcefile~guess_hcore.f90->sourcefile~guess.f90 sourcefile~guess_hcore.f90->sourcefile~mathlib.f90 sourcefile~guess_huckel.f90 guess_huckel.F90 sourcefile~guess_huckel.f90->sourcefile~guess.f90 sourcefile~guess_huckel.f90->sourcefile~huckel.f90 sourcefile~guess_huckel.f90->sourcefile~mathlib.f90 sourcefile~guess_json.f90 guess_json.F90 sourcefile~guess_json.f90->sourcefile~guess.f90 sourcefile~hf_gradient.f90 hf_gradient.F90 sourcefile~hf_gradient.f90->sourcefile~mathlib.f90 sourcefile~hf_gradient.f90->sourcefile~dft.f90 sourcefile~hf_gradient.f90->sourcefile~grd1.f90 sourcefile~resp.f90 resp.F90 sourcefile~resp.f90->sourcefile~mathlib.f90 sourcefile~scf.f90 scf.F90 sourcefile~scf.f90->sourcefile~guess.f90 sourcefile~scf.f90->sourcefile~mathlib.f90 sourcefile~scf.f90->sourcefile~dft.f90 sourcefile~scf_converger.f90 scf_converger.F90 sourcefile~scf.f90->sourcefile~scf_converger.f90 sourcefile~scf_converger.f90->sourcefile~mathlib.f90 sourcefile~tdhf_energy.f90 tdhf_energy.F90 sourcefile~tdhf_energy.f90->sourcefile~mathlib.f90 sourcefile~tdhf_energy.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_energy.f90->sourcefile~dft.f90 sourcefile~tdhf_energy.f90->sourcefile~dft_gridint_fxc.f90 sourcefile~tdhf_gradient.f90 tdhf_gradient.F90 sourcefile~tdhf_gradient.f90->sourcefile~mathlib.f90 sourcefile~tdhf_gradient.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_gradient.f90->sourcefile~dft.f90 sourcefile~tdhf_gradient.f90->sourcefile~grd1.f90 sourcefile~tdhf_mrsf_energy.f90 tdhf_mrsf_energy.F90 sourcefile~tdhf_mrsf_energy.f90->sourcefile~mathlib.f90 sourcefile~tdhf_mrsf_energy.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_sf_lib.f90 tdhf_sf_lib.F90 sourcefile~tdhf_mrsf_energy.f90->sourcefile~tdhf_sf_lib.f90 sourcefile~tdhf_sf_energy.f90 tdhf_sf_energy.F90 sourcefile~tdhf_sf_energy.f90->sourcefile~mathlib.f90 sourcefile~tdhf_sf_energy.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_sf_energy.f90->sourcefile~tdhf_sf_lib.f90 sourcefile~tdhf_sf_lib.f90->sourcefile~mathlib.f90 sourcefile~tdhf_sf_lib.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_z_vector.f90 tdhf_z_vector.F90 sourcefile~tdhf_z_vector.f90->sourcefile~mathlib.f90 sourcefile~tdhf_z_vector.f90->sourcefile~tdhf_lib.f90 sourcefile~tdhf_z_vector.f90->sourcefile~dft.f90 sourcefile~tdhf_z_vector.f90->sourcefile~dft_gridint_fxc.f90 sourcefile~tdhf_z_vector.f90->sourcefile~dft_gridint_gxc.f90 sourcefile~tdhf_z_vector.f90->sourcefile~tdhf_sf_lib.f90 sourcefile~hf_energy.f90 hf_energy.f90 sourcefile~hf_energy.f90->sourcefile~dft.f90 sourcefile~hf_energy.f90->sourcefile~scf.f90

Source Code

module eigen
  use precision, only: dp
  use mathlib_types, only: blas_int
  use messages, only: show_message, WITH_ABORT
  use oqp_linalg

  implicit none

  private
  public :: diag_symm_packed
  public :: diag_symm_full
  public :: schmd
  real(dp), parameter :: zero = 0.0_dp, two = 2.0_dp
contains

!>  @brief Find eigenvalues and eigenvectors of symmetric matrix
!>         in packed format
!>  @param[in]     mode   algorithm of diagonalization (not used now)
!>  @param[in]     n      matrix dimension
!>  @param[in]     ldvect leading dimension of eigenvector matrix
!>  @param[in]     nvect  required number of eigenvectors
!>  @param[in,out] h      matrix to be diagonalized
!>  @param[out]    eig    eigenvalues
!>  @param[out]    vector eigenvectors
!>  @param[out]    ierr   status
  subroutine diag_symm_packed(mode, ldvect, nvect, n, h, eig, vector, ierr)
    use messages, only: show_message, WITH_ABORT, WITHOUT_ABORT
!
    integer, intent(in) :: mode
    integer, intent(in) :: ldvect, nvect, n
    integer, optional, intent(out) :: ierr
    real(dp), intent(inout) :: h(*)
    real(kind=dp), intent(out) :: eig(*), vector(*)

    integer(blas_int), dimension(:), allocatable :: iwork, ifail
    integer(blas_int) :: ldvect_, n_, nvect_, info, ione
    integer :: iok
    real(dp), dimension(:), allocatable :: work
    real(dp) :: abstol, dlamch
    logical :: fatal

    character(16) :: driver

    ldvect_ = int(ldvect, kind=blas_int)
    n_      = int(n, kind=blas_int)
    nvect_  = int(nvect, kind=blas_int)
    ione    = 1

    fatal = WITH_ABORT
    if (present(ierr)) fatal = WITHOUT_ABORT

    allocate (work(n*8), iwork(n*5), ifail(n), stat=iok)
    if (iok /= 0) then
      if (present(ierr)) ierr = iok
      call show_message('Cannot allocate memory', fatal)
      return
    end if

    if (nvect == n .and. ldvect >= n) then
      driver = 'DSPEV'
      call dspev('V', 'U', n_, h, eig, vector, ldvect_, work, info)
    else
      abstol = two*DLAMCH('S')
      driver = 'DSPEVX'
      call dspevx('V', 'A', 'U', &
            ldvect_, h, zero, zero, ione, ione, abstol, n_, &
            eig, vector, nvect_, work, iwork, ifail, info)
    end if

    if (present(ierr)) ierr = info

    if (info /= 0) then
      call show_message('(A,I0)', &
              trim(driver)//' FAILED! INFO: ', int(info), fatal)
    end if

  end subroutine diag_symm_packed

!>  @brief Find eigenvalues and eigenvectors of symmetric matrix
!>         in full format
!>  @param[in]     mode   algorithm of diagonalization (not used now)
!>  @param[in]     n      matrix dimension
!>  @param[in,out] a      matrix to be diagonalized, overwritten by
!>                        the eigenvectors on the exit
!>  @param[in]     lda    leading dimension of the matrix
!>  @param[out]    eig    eigenvalues
!>  @param[out]    ierr   status
  subroutine diag_symm_full(mode, n, a, lda, eival, ierr)
    use messages, only: show_message, WITH_ABORT, WITHOUT_ABORT
!
    integer, intent(in) :: mode
    integer, intent(in) :: n, lda
    real(dp), intent(inout) :: a(*)
    real(kind=dp), intent(out) :: eival(*)
    integer, optional, intent(out) :: ierr

    integer(blas_int) :: lda_, n_, info, ione, lwork
    integer :: iok
    real(dp), dimension(:), allocatable :: work
    real(dp) :: rwork(1)
    logical :: fatal
    character(16) :: driver

    lda_    = int(lda, kind=blas_int)
    n_      = int(n, kind=blas_int)
    ione    = 1

    fatal = WITH_ABORT
    if (present(ierr)) fatal = WITHOUT_ABORT

    driver = 'DSYEV'
    call dsyev('V', 'U', n_, a, lda_, eival, rwork, -1_blas_int, info)
    lwork = int(nint(rwork(1)), blas_int)
    allocate (work(lwork), stat=iok)
    if (iok /= 0) then
      if (present(ierr)) ierr = iok
      call show_message('Cannot allocate memory', fatal)
      return
    end if
    call dsyev('V', 'U', n_, a, lda_, eival, work, lwork, info)


    if (present(ierr)) ierr = info

    if (info /= 0) then
      call show_message('(A,I0)', &
              trim(driver)//' FAILED! INFO: ', int(info), fatal)
    end if

  end subroutine diag_symm_full

  subroutine schmd(v, m, n, ldv, x)
    use, intrinsic :: iso_fortran_env, only: real64
    use messages, only: show_message, WITH_ABORT
    implicit none

    integer, intent(IN) :: ldv, m, n
    real(real64), intent(INOUT) :: v(ldv, n), x(n)

    real(real64), allocatable :: work(:)
    integer :: lwork
    integer :: info
    real(real64) :: wrksize(1)

    if (M > N) then
      call show_message("SCHMD: M > N", WITH_ABORT)
    end if
    if (N > LDV) then
      call show_message("SCHMD: N > LDV", WITH_ABORT)
    end if
!   Householder QR-based version using LAPACK:
    call dgeqrf(n, m, v, ldv, x, wrksize, -1, info)
    lwork = max(int(wrksize(1)), n)
    allocate (work(lwork))
    call dgeqrf(n, m, v, ldv, x, work, lwork, info)
    call dorgqr(n, n, m, v, ldv, x, work, lwork, info)
  end subroutine schmd
end module eigen