rpaeig Subroutine

public subroutine rpaeig(ee, vl, vr, apb, amb, scr, tamm_dancoff)

Uses

  • proc~~rpaeig~~UsesGraph proc~rpaeig rpaeig module~eigen eigen proc~rpaeig->module~eigen module~precision precision proc~rpaeig->module~precision module~eigen->module~precision module~mathlib_types mathlib_types module~eigen->module~mathlib_types module~messages messages module~eigen->module~messages module~oqp_linalg oqp_linalg module~eigen->module~oqp_linalg iso_fortran_env iso_fortran_env module~precision->iso_fortran_env module~messages->module~precision comm_IOFILE comm_IOFILE module~messages->comm_IOFILE comm_PAR comm_PAR module~messages->comm_PAR module~io_constants io_constants module~messages->module~io_constants module~blas_wrap blas_wrap module~oqp_linalg->module~blas_wrap module~lapack_wrap lapack_wrap module~oqp_linalg->module~lapack_wrap module~blas_wrap->module~precision module~blas_wrap->module~mathlib_types module~blas_wrap->module~messages module~lapack_wrap->module~precision module~lapack_wrap->module~mathlib_types module~lapack_wrap->module~messages

@brief Diagonalize small reduced RPA matrix

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out), dimension(:) :: ee
real(kind=dp), intent(out), dimension(:,:) :: vl
real(kind=dp), intent(out), dimension(:,:) :: vr
real(kind=dp), intent(in), dimension(:,:) :: apb
real(kind=dp), intent(inout), dimension(:,:) :: amb
real(kind=dp), intent(inout), dimension(:) :: scr
logical, intent(in) :: tamm_dancoff

Calls

proc~~rpaeig~~CallsGraph proc~rpaeig rpaeig proc~diag_symm_packed diag_symm_packed proc~rpaeig->proc~diag_symm_packed proc~oqp_dgemm_i64 oqp_dgemm_i64 proc~rpaeig->proc~oqp_dgemm_i64 proc~oqp_dtrttp_i64 oqp_dtrttp_i64 proc~rpaeig->proc~oqp_dtrttp_i64 dspev dspev proc~diag_symm_packed->dspev dspevx dspevx proc~diag_symm_packed->dspevx interface~show_message show_message proc~diag_symm_packed->interface~show_message dgemm dgemm proc~oqp_dgemm_i64->dgemm proc~oqp_dgemm_i64->interface~show_message dtrttp dtrttp proc~oqp_dtrttp_i64->dtrttp proc~oqp_dtrttp_i64->interface~show_message

Called by

proc~~rpaeig~~CalledByGraph proc~rpaeig rpaeig proc~tdhf_energy tdhf_energy proc~tdhf_energy->proc~rpaeig proc~tdhf_mrsf_energy tdhf_mrsf_energy proc~tdhf_mrsf_energy->proc~rpaeig proc~tdhf_sf_energy tdhf_sf_energy proc~tdhf_sf_energy->proc~rpaeig proc~tdhf_energy_c tdhf_energy_C proc~tdhf_energy_c->proc~tdhf_energy proc~tdhf_mrsf_energy_c tdhf_mrsf_energy_C proc~tdhf_mrsf_energy_c->proc~tdhf_mrsf_energy proc~tdhf_sf_energy_c tdhf_sf_energy_C proc~tdhf_sf_energy_c->proc~tdhf_sf_energy

Source Code

  subroutine rpaeig(ee,vl,vr,apb,amb,scr,tamm_dancoff)

    use precision, only: dp
    use eigen, only: diag_symm_packed

    implicit none

    real(kind=dp), intent(out), dimension(:) :: ee
    real(kind=dp), intent(out), dimension(:,:) :: vl, vr
    real(kind=dp), intent(in), dimension(:,:) :: apb
    real(kind=dp), intent(inout), dimension(:,:) :: amb
    real(kind=dp), intent(inout), dimension(:) :: scr
    logical, intent(in) :: tamm_dancoff

    integer :: ierr, j, nvec

    nvec = ubound(vl, 2)

    if (tamm_dancoff) then

  !   Diagonailze A: VR
      if (nvec==1) then
        ee(1) = vr(1,1)
        vr(1,1) = 1.0_dp
      else
        call dtrttp('u', nvec, apb, nvec, scr, ierr)
        call diag_symm_packed(1,nvec,nvec,nvec,scr,ee,vr,ierr)
      end if
      return
    end if

!   sqrt(A-B)
    if (nvec==1) then
      amb(1,1) = sqrt(amb(1,1))
    else
      call dtrttp('u', nvec, amb, nvec, scr, ierr)
      call diag_symm_packed(1,nvec,nvec,nvec,scr,ee,vr,ierr)
      ee(1:nvec) = sign(sqrt(abs(ee(1:nvec))),ee(1:nvec))
      do j = 1, nvec
        vl(:,j) = vr(:,j)*ee(j)
      end do
      call dgemm('n','t',nvec,nvec,nvec, &
                 1.0_dp,vr,nvec,vl,nvec, &
                 0.0_dp,amb,nvec)
    end if

!   Form sqrt(A-B)*(A+B)*sqrt(A-B)
!   (A+B)*sqrt(A-B) : VL
    call dgemm('n','n',nvec,nvec,nvec, &
               1.0_dp,apb,nvec,amb,nvec, &
               0.0_dp,vl,nvec)
!   sqrt(A-B)*(A+B)*sqrt(A-B) : VR
    call dgemm('n','n',nvec,nvec,nvec, &
               1.0_dp,amb,nvec,vl,nvec, &
               0.0_dp,vr,nvec)

!   Diagonailze sqrt(A-B)*(A+B)*sqrt(A-B) : VR
    if (nvec==1) then
      ee(1) = vr(1,1)
      vl(1,1) = 1.0_dp
    else
      call dtrttp('u', nvec, vr, nvec, scr, ierr)
      call diag_symm_packed(1,nvec,nvec,nvec,scr,ee,vl,ierr)
    end if

!   Current vector VL is sqrt(1/(A-B)))|X+Y>.

!   VL into right eigenvector  VR = |X+Y>
    call dgemm('n','n',nvec,nvec,nvec, &
               1.0_dp,amb,nvec,vl,nvec, &
               0.0_dp,vr,nvec)

!   Left eigenvector   VL = = 1/E (A+B)|X+Y>
    call dgemm('n','n',nvec,nvec,nvec, &
               1.0_dp,apb,nvec,vr,nvec, &
               0.0_dp,vl,nvec)

    do j = 1, nvec
      vl(1:nvec,j) = vl(1:nvec,j)/sign(sqrt(abs(ee(j))),ee(j))
    end do

  end subroutine rpaeig