Entry 4705

k.p matrix calculation routine

   

Submitted by anonymous on May 26, 2010 at 11:02 p.m.
Language: Fortran. Code size: 8.3 KB.

subroutine electronic_kdotp_matrices(wvfn,dens,eigenvalues,nk,Gfrac,Bfrac)
    use constants, only: dp,cmplx_0,cmplx_i,cmplx_1,two_pi
    use comms, only: on_root_node
    use basis, only: pw_gk_vector,num_plane_waves_kp
    use cell, only: current_cell,kpoints_on_node,kpoint_weights_on_node
    use density, only: electron_density
    use ion, only: max_ps_projectors
    use pot, only : potential,pot_allocate,pot_deallocate
    use locpot, only : locpot_calculate
    use nlpot, only : nlpot_apply_velocity,nlpot_calculate_d
    use parameters, only : seedname
    use wave, only: wavefunction,band,wave_allocate,wave_initialise,wave_deallocate
    use trace, only: trace_entry,trace_exit
    use io, only: stdout,io_abort,io_atomic_to_unit,io_allocate_abort
    
    implicit none

    ! arguments
    type(wavefunction), intent(inout) :: wvfn !inout for nlpot_apply_velocity
    type(electron_density),intent(in) :: dens
    real(kind=dp),dimension(:,:,:), intent(in) :: eigenvalues
    integer, intent(in) :: nk
    complex(kind=dp),dimension(:,:,:,:),intent(out) :: Gfrac   ! Fractional Gradient vector
    complex(kind=dp),dimension(:,:,:,:,:),intent(out) :: Bfrac ! Fractional Curvature tensor


    ! local variables
    character(len=1), dimension(3) :: xyz=(/'X','Y','Z'/)
    integer :: ns,nb1,nb2,nw1,nc1,nc2  ! loop indices
    integer :: status
    type(wavefunction) :: tmp_wvfn
    complex(kind=dp),allocatable,dimension(:,:,:,:,:) :: momentum
    complex(kind=dp),allocatable,dimension(:,:,:,:) :: G       ! Gradient vector
    complex(kind=dp),allocatable,dimension(:,:,:,:,:) :: B     ! Curvature tensor
    complex(kind=dp) :: Btmp(3,3)                              ! Temporary Curvature
    complex(kind=dp),allocatable,dimension(:,:,:,:) :: kB      ! Curvature tensor premultiplied by k direction

    real(kind=dp) :: jacdet ! Fractional -> Cartesian Jacobian Determinant
    real(kind=dp) :: prodxyz ! Volume element

    real(kind=dp) :: diff_fdk(3)
    real(kind=dp) :: prod_dfdk(3)
    real(kind=dp) :: diff_fdk_sq(3)
    real(kind=dp) :: prod_dfdk_sq(3)
    real(kind=dp) :: diff_fdk_cu(3)


    ! nl x
    real(kind=dp), allocatable, dimension(:,:,:,:,:)::nl_d
    ! Potentials
    type(potential)::pot_loc     ! Up potential (or total potential for nspins=1 calculations)
    real(kind=dp) :: pot_energy

    write(*,*) "wvfn,nbands :", size(wvfn%nbands,1),size(wvfn%nbands,2), "<-- ja531"

    call trace_entry('electronic_kdotp_matrices',status)

    allocate(momentum(wvfn%nbands_max,wvfn%nbands_max,wvfn%nkpts,wvfn%nspins,3))
    allocate(G(wvfn%nbands_max,wvfn%nkpts,wvfn%nspins,3))
    allocate(B(wvfn%nbands_max,wvfn%nkpts,wvfn%nspins,3,3))
    allocate(kB(wvfn%nbands_max,wvfn%nkpts,wvfn%nspins,3))
 
    call wave_allocate(tmp_wvfn,trim(seedname)//'.kpwfn',nb=wvfn%nbands_max,nk=wvfn%nkpts,ns=wvfn%nspins)

    call wave_initialise(tmp_wvfn,'Z')

    ! ** Allocate non-local weights

    allocate(nl_d(max_ps_projectors,max_ps_projectors,current_cell%max_ions_in_species, &
         current_cell%num_species,wvfn%nspins),stat=status)
    if (status/=0) call io_allocate_abort('nl_d','electronic_kdotp_matrices')

    ! ** Allocate potentials

    call pot_allocate(pot_loc,dens%nspins,'R')

    ! ** Calculate local potential and non-local weights

    call locpot_calculate(dens,pot_loc,pot_energy)
    call nlpot_calculate_d(pot_loc,nl_d)


    momentum=cmplx_0
    G=cmplx_0
    B=cmplx_0
    kB=cmplx_0

!write(*,*) "--> size", size(Gfrac,1),size(Gfrac,2),size(Gfrac,3),size(Gfrac,4)
    ! Calculate momentum matrix
    do ns=1,wvfn%nspins
!       do nk=1,wvfn%nkpts
          do nc1=1,3
             call nlpot_apply_velocity(xyz(nc1),wvfn,nk,ns,nl_d,eigenvalue=eigenvalues(:,nk,ns),Vel_wvfn=tmp_wvfn)
             do nb1=1,wvfn%nbands_max
                do nb2=1,wvfn%nbands_max
                   do nw1=1,num_plane_waves_kp(nk)
                      momentum(nb1,nb2,nk,ns,nc1)=momentum(nb1,nb2,nk,ns,nc1)+(tmp_wvfn%coeffs(nw1,nb1,nk,ns)*&
                           &conjg(wvfn%coeffs(nw1,nb2,nk,ns)))
                   end do
                end do
             end do
          end do
!       end do
    end do

if(any(real(momentum,dp)<0.0_dp)) write(*,*) "count:", count(real(momentum,dp)<0.0_dp),&
     & count(real(momentum,dp)>0.0_dp), count(real(momentum,dp).eq.0.0_dp)
!if(any(aimag(momentum)>epsilon(1.0_dp))) write(*,*) "imagy:", maxval(imagpart(momentum))


    ! Calculate G (Gradient) vector
    G=0.0_dp
    do ns=1,wvfn%nspins
 !      do nk=1,wvfn%nkpts
          do nb1=1,wvfn%nbands_max
             do nc1=1,3
                G(nb1,nk,ns,nc1)= momentum(nb1,nb1,nk,ns,nc1)
             end do
          end do
 !      end do
    end do

    ! Transform G into fractional basis
    Gfrac=0.0_dp
    do ns=1,wvfn%nspins
 !      do nk=1,wvfn%nkpts
          do nb1=1,wvfn%nbands_max
             !do nc1=1,3
             !   Gfrac(nb1,nk,ns,nc1)= dot_product(current_cell%recip_lattice(nc1,:),G(nb1,nk,ns,:))
             !end do
             Gfrac(nb1,nk,ns,:)=matmul(current_cell%recip_lattice,G(nb1,nk,ns,:))
          end do
 !      end do
    end do

Gfrac=Gfrac/two_pi

    !B=1.0_dp
    ! set diagonal elements of B to 1.0 to begin with.
    do ns=1,wvfn%nspins
 !      do nk=1,wvfn%nkpts
          do nb1=1,wvfn%nbands_max
!             do nb2=1,wvfn%nbands_max
                do nc1=1,3
                   B(nb1,nk,ns,nc1,nc1)=+cmplx_1
                end do
 !            end do
          end do
 !      end do
    end do

    ! Calculate B (Curvature) Matrix
    do ns=1,wvfn%nspins
 !      do nk=1,wvfn%nkpts
          do nb1=1,wvfn%nbands_max
             do nb2=1,wvfn%nbands_max
                if(nb1.eq.nb2) cycle ! catch 1st divide by zero
                if(abs(eigenvalues(nb1,nk,ns)-eigenvalues(nb2,nk,ns)).le.1e-7) cycle !epsilon(1.0_dp)) cycle ! catch 2nd divide by zero
                do nc1=1,3
                   do nc2=1,3
                      B(nb1,nk,ns,nc1,nc2)=B(nb1,nk,ns,nc1,nc2)+(((momentum(nb1,nb2,nk,ns,nc1)*&
                           &conjg(momentum(nb2,nb1,nk,ns,nc2)))+(momentum(nb1,nb2,nk,ns,nc2)*&
                           &conjg(momentum(nb2,nb1,nk,ns,nc1))))/(eigenvalues(nb1,nk,ns)-&
                           &eigenvalues(nb2,nk,ns)))
                   end do
                end do
!                write(*,*) "eigthing-->",eigenvalues(nb1,nk,ns)-eigenvalues(nb2,nk,ns)
             end do
          end do
!       end do
    end do
if(any(real(B,dp)<0.0_dp)) write(*,*) "count:", count(real(B,dp)<0.0_dp), count(real(B,dp)>0.0_dp), count(real(B,dp).eq.0.0_dp)
    B=B*0.5_dp
 
    ! Transform B into fractional basis
    do ns=1,wvfn%nspins
!       do nk=1,wvfn%nkpts
          do nb1=1,wvfn%nbands_max
             do nc1=1,3
                do nc2=1,3
                   Btmp=matmul((current_cell%recip_lattice),B(nb1,nk,ns,:,:))
                   Bfrac(nb1,nk,ns,:,:)=matmul(Btmp,transpose(current_cell%recip_lattice))
!                   call dgemm("T","N",3,3,3,1.0_dp,current_cell%recip_lattice,size(current_cell%recip_lattice,1),B(nb1,nk,ns,:,:)...)
                end do
             end do
!             write(*,*) "maxB-->",maxval(abs(Bfrac(nb1,nk,ns,:,:))),maxloc(abs(Bfrac(nb1,nk,ns,:,:)))
          end do
!       end do
    end do
    
if(any(real(Bfrac,dp)<0.0_dp)) write(*,*) "countfrac:", count(real(Bfrac,dp)<0.0_dp), &
     &count(real(Bfrac,dp)>0.0_dp), count(real(Bfrac,dp).eq.0.0_dp)
!Bfrac=Bfrac/two_pi
Bfrac=Bfrac/(two_pi**2)

    deallocate(momentum,stat=status)
    if (status/=0) call io_abort('error deallocating momentum in electronic_kdotp_matrices')
    deallocate(G,stat=status)
    if (status/=0) call io_abort('error deallocating G in electronic_kdotp_matrices')
    deallocate(B,stat=status)
    if (status/=0) call io_abort('error deallocating B in electronic_kdotp_matrices')
    deallocate(kB,stat=status)
    if (status/=0) call io_abort('error deallocating kB in electronic_kdotp_matrices')

    call wave_deallocate(tmp_wvfn)

    deallocate(nl_d,stat=status)
    if (status/=0) call io_abort('error deallocating nl_d in electronic_kdotp_matrices')

    call pot_deallocate(pot_loc)

    call trace_exit('electronic_kdotp_matrices',status)

end subroutine electronic_kdotp_matrices

This snippet took 0.04 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).