LCOV - code coverage report
Current view: top level - src/72_response - m_ddk.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.3 % 328 247
Test Date: 2026-09-19 15:24:51 Functions: 61.1 % 18 11

            Line data    Source code
       1              : !!****m* ABINIT/m_ddk
       2              : !! NAME
       3              : !!  m_ddk
       4              : !!
       5              : !! FUNCTION
       6              : !!  Objects and methods to extract data from DDK files.
       7              : !!  The DDK files are binary (soon also netcdf) files with Hamiltonian derivatives
       8              : !!  wrt k, and the corresponding wave functions
       9              : !!
      10              : !! COPYRIGHT
      11              : !! Copyright (C) 2016-2026 ABINIT group (MG, HM, MJV)
      12              : !! This file is distributed under the terms of the
      13              : !! GNU General Public License, see ~abinit/COPYING
      14              : !! or http://www.gnu.org/copyleft/gpl.txt .
      15              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
      16              : !!
      17              : !! SOURCE
      18              : 
      19              : #if defined HAVE_CONFIG_H
      20              : #include "config.h"
      21              : #endif
      22              : 
      23              : #include "abi_common.h"
      24              : 
      25              : module m_ddk
      26              : 
      27              :  use defs_basis
      28              :  use m_abicore
      29              :  use m_errors
      30              :  use m_xmpi
      31              :  use m_nctk
      32              :  use m_hdr
      33              :  use m_dtset
      34              :  use m_krank
      35              :  use m_crystal
      36              :  use m_mpinfo
      37              :  use m_cgtools
      38              :  use m_hamiltonian
      39              :  use m_initylmg
      40              :  use m_pawcprj
      41              :  use m_getgh1c
      42              :  use netcdf
      43              : 
      44              :  use m_fstrings,      only : strcat, sjoin, itoa, ktoa
      45              :  use m_io_tools,      only : iomode_from_fname
      46              :  use m_time,          only : cwtime, cwtime_report
      47              :  use defs_abitypes,   only : MPI_type
      48              :  use defs_datatypes,  only : pseudopotential_type
      49              :  use m_vkbr,          only : vkbr_t, nc_ihr_comm, vkbr_init, vkbr_free
      50              :  use m_pawtab,        only : pawtab_type
      51              :  use m_wfk,           only : wfk_read_ebands !, wfk_read_h1mat
      52              :  use m_wfd,           only : wfd_t, wave_t
      53              :  use m_ebands,        only : ebands_t
      54              : 
      55              :  implicit none
      56              : 
      57              :  private
      58              : !!***
      59              : 
      60              :  public :: ddk_red2car           ! Convert band velocities from cartesian to reduced coordinates
      61              : 
      62              : !!***
      63              : 
      64              :  type, private :: ham_targets_t
      65              :    real(dp),allocatable :: ffnlk(:,:,:,:), ffnl1(:,:,:,:)
      66              :    real(dp),allocatable :: kpg_k(:,:), kpg1_k(:,:)
      67              :    real(dp),allocatable :: ph3d(:,:,:), ph3d1(:,:,:)
      68              :    real(dp),allocatable :: dkinpw(:), kinpw1(:)
      69              :    contains
      70              :      procedure :: free => ham_targets_free   ! Free memory.
      71              :  end type ham_targets_t
      72              : 
      73              : 
      74              : !!****t* m_ddk/ddkop_t
      75              : !! NAME
      76              : !!  ddkop_t
      77              : !!
      78              : !! FUNCTION
      79              : !!  This object provides a simplified interface to compute matrix elements of the
      80              : !!  velocity operator with the DFPT routines.
      81              : !!
      82              : !! SOURCE
      83              : 
      84              :  type,public :: ddkop_t
      85              : 
      86              :   integer :: ipert
      87              :   ! Perturbation type: natom + 1
      88              : 
      89              :   integer :: inclvkb
      90              :   ! Option for calculating the matrix elements of [Vnl,r].
      91              :   ! 0 to exclude commutator, 2 to include it
      92              : 
      93              :   integer :: usepaw
      94              :   ! 0 for NC, 1 for PAW
      95              : 
      96              :   integer :: mpw
      97              :   ! Maximum number of plane-waves over k-points (used to dimension arrays)
      98              : 
      99              :   real(dp) :: kpoint(3)
     100              :   ! K-point (set in setup_spin_kpoint)
     101              : 
     102              :   real(dp) :: eig0nk
     103              : 
     104              :   real(dp) :: dfpt_sciss = zero
     105              : 
     106              :   real(dp) :: rprimd(3,3)
     107              : 
     108              :   type(MPI_type),pointer :: mpi_enreg => null()
     109              : 
     110              :   type(gs_hamiltonian_type) :: gs_hamkq(3)
     111              : 
     112              :   type(rf_hamiltonian_type) :: rf_hamkq(3)
     113              : 
     114              :   type(ham_targets_t), private :: htg(3)
     115              :   ! Store arrays targetted by the hamiltonians.
     116              : 
     117              :   real(dp), allocatable :: gh1c(:,:,:)
     118              :    !gh1c, (2, npw_k*nspinor, 3))
     119              : 
     120              :   real(dp), allocatable :: gs1c(:,:,:)
     121              :    ! gs1c, (2, npw_k*nspinor, 3*psps%usepaw))
     122              : 
     123              :  contains
     124              : 
     125              :    procedure :: init => ddkop_init
     126              :     ! Build object
     127              : 
     128              :    procedure :: setup_spin_kpoint => ddkop_setup_spin_kpoint
     129              :     ! Prepare application of dH/dk for given spin, k-point.
     130              : 
     131              :    procedure :: apply => ddkop_apply
     132              :     ! Apply dH/dk to input wavefunction.
     133              : 
     134              :    procedure :: get_braket => ddkop_get_braket
     135              :     ! Compute matrix element (complex results) in cartesian coords.
     136              : 
     137              :    procedure :: get_ihr_comm => ddkop_get_ihr_comm
     138              :     ! Compute matrix elements of i[H,r] (complex results) in cartesian coords.
     139              : 
     140              :    procedure :: get_vdiag => ddkop_get_vdiag
     141              :     ! Compute diagonal matrix element (real) in cartesian coords.
     142              : 
     143              :    procedure :: get_vnondiag => ddkop_get_vnondiag
     144              :     ! Compute off diagonal matrix elements in cartesian coords.
     145              : 
     146              :    procedure :: free => ddkop_free
     147              :     ! Free memory.
     148              : 
     149              :  end type ddkop_t
     150              : !!***
     151              : 
     152              : !!****t* m_ddk/ddkstore_t
     153              : !! NAME
     154              : !!  ddkstore_t
     155              : !!
     156              : !! FUNCTION
     157              : !!  This object stores the matrix elements of the velocity operator computed with the DFPT routines.
     158              : !!
     159              : !! SOURCE
     160              : 
     161              :  type,public :: ddkstore_t
     162              : 
     163              :    integer :: bmin = 1, bmax = -1
     164              :    ! Min and max band index
     165              : 
     166              :    character(len=50) :: mode = "reduced"
     167              :     ! "cart" or "reduced"
     168              : 
     169              :    logical :: only_diago = .False.
     170              :    ! True if we are computing only the diagonal elements
     171              : 
     172              :    real(dp),allocatable :: dipoles(:,:,:,:,:,:)
     173              :     ! (3, 2, mband, mband, nkpt, nsppol))
     174              : 
     175              :    real(dp),allocatable :: vdiago(:,:,:,:)
     176              :     ! (3, bmin:bmax, nkpt, nsppol)
     177              : 
     178              :    real(dp),allocatable :: vmat(:,:,:,:,:,:)
     179              :     ! (2, 3, bmin:bmax, bmin:bmax, nkpt, nsppol))
     180              : 
     181              :  contains
     182              : 
     183              :    procedure :: compute_ddk => ddkstore_compute_ddk
     184              :     ! Calculate DDK matrix elements (diago or full b,b' matrix).
     185              :     ! Return results in datatype. Optionally, save results to disk in EVK format.
     186              : 
     187              :    procedure :: free => ddkstore_free
     188              :     ! Free memory.
     189              : 
     190              :  end type ddkstore_t
     191              : !!***
     192              : 
     193              : CONTAINS
     194              : 
     195              : !----------------------------------------------------------------------
     196              : 
     197              : !!****f* m_ddk/ddkstore_compute_ddk
     198              : !! NAME
     199              : !!  ddkstore_compute_ddk
     200              : !!
     201              : !! FUNCTION
     202              : !!  Calculate the DDK matrix elements using the commutator formulation.
     203              : !!
     204              : !! INPUTS
     205              : !!  prefix: Prefix for output EVK file. Empty if output files are not wanted
     206              : !!
     207              : !! SOURCE
     208              : 
     209            3 : subroutine ddkstore_compute_ddk(ds, wfk_path, prefix, dtset, psps, pawtab, ngfftc, comm)
     210              : 
     211              : !Arguments ------------------------------------
     212              : !scalars
     213              :  class(ddkstore_t),intent(inout) :: ds
     214              :  character(len=*),intent(in) :: wfk_path, prefix
     215              :  integer,intent(in) :: comm
     216              :  type(dataset_type),intent(in) :: dtset
     217              :  type(pseudopotential_type),intent(in) :: psps
     218              :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
     219              : !arrays
     220              :  integer,intent(in) :: ngfftc(18)
     221              : 
     222              : !Local variables ------------------------------
     223              : !scalars
     224              :  integer,parameter :: master = 0
     225              :  integer :: mband, nbcalc, nsppol, ib_v, ib_c, mpw, spin, nspinor, nkpt, nband_k, npw_k
     226              :  integer :: ii, ik, bmin, bmax, istwf_k, idir, my_rank, nproc, ierr, bstop
     227              :  real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all
     228              :  integer :: ncerr, ncid
     229              :  character(len=500) :: msg
     230              :  character(len=fnlen) :: fname
     231              :  logical :: write_ncfile
     232            3 :  type(wfd_t) :: wfd
     233            3 :  type(vkbr_t) :: vkbr
     234            3 :  type(ebands_t) :: ebands
     235          156 :  type(crystal_t) :: cryst
     236            3 :  type(hdr_type) :: tmp_hdr, hdr
     237           30 :  type(ddkop_t) :: ddkop
     238              :  type(wave_t),pointer :: wave_v, wave_c
     239              : !arrays
     240            3 :  integer,allocatable :: distrib_mat(:,:,:,:), distrib_diago(:,:,:), nband(:,:), kg_k(:,:)
     241            6 :  logical,allocatable :: bks_mask(:,:,:), keep_ur(:,:,:)
     242              :  real(dp) :: kpt(3), vv(2, 3)
     243            3 :  real(dp),allocatable :: cg_c(:,:), cg_v(:,:)
     244              :  complex(dp) :: vg(3), vr(3)
     245            3 :  complex(gwp),allocatable :: ihrc(:,:), ug_c(:), ug_v(:)
     246            3 :  type(pawcprj_type),allocatable :: cwaveprj(:,:)
     247              : !************************************************************************
     248              : 
     249            3 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
     250              : 
     251            9 :  if (my_rank == master) call wrtout([std_out, ab_out], " Computation of velocity matrix elements (DDK)", newlines=1)
     252              : 
     253            3 :  ABI_CHECK(psps%usepaw == 0, "PAW not implemented")
     254              : 
     255              :  ! Get ebands and hdr from WFK file.
     256            3 :  ebands = wfk_read_ebands(wfk_path, comm, out_hdr=hdr)
     257            3 :  cryst = hdr%get_crystal()
     258              : 
     259              :  ! Extract important dimensions from hdr%
     260            3 :  nkpt    = hdr%nkpt
     261            3 :  nsppol  = hdr%nsppol
     262            3 :  nspinor = hdr%nspinor
     263            3 :  mband   = hdr%mband
     264              : 
     265              :  ! Define band range
     266              :  ! TODO: Perhaps one should allocate output arrays using bmin:bmax
     267              :  ! and allow for nc output only if bmin == 1 and bmax == mband
     268            3 :  if (ds%bmax == -1) ds%bmax = mband
     269              : 
     270            3 :  if (ds%bmin < 1 .or. ds%bmin > mband .or. ds%bmax > mband .or. ds%bmin > ds%bmax) then
     271            0 :    ABI_ERROR(sjoin("Invalid value for bmin, bmax", itoa(ds%bmin), itoa(ds%bmax), "with mband:", itoa(mband)))
     272              :  end if
     273              : 
     274            3 :  bmin = ds%bmin; bmax = ds%bmax
     275            3 :  nbcalc  = bmax - bmin + 1
     276            3 :  write_ncfile = len_trim(prefix) > 0
     277            3 :  if (write_ncfile .and. .not. (bmin == 1 .and. bmax == mband) ) then
     278            0 :    write_ncfile = .False.
     279            0 :    ABI_WARNING("Cannot write ncfile if .not. (bmin == 1 .and. bmax == mband)")
     280              :  end if
     281              : 
     282            3 :  if (my_rank == master) then
     283            3 :    write(ab_out, "(a)")" Parameters extracted from the Abinit header:"
     284            3 :    write(ab_out, "(a, f5.1)") '    ecut:    ', hdr%ecut
     285            3 :    write(ab_out, "(a, i0)")   '    nkpt:    ', nkpt
     286            3 :    write(ab_out, "(a, i0)")   '    mband:   ', mband
     287            3 :    write(ab_out, "(a, i0)")   '    nsppol:  ', nsppol
     288            3 :    write(ab_out, "(a, i0)")   '    nspinor: ', nspinor
     289            3 :    write(ab_out, "(a, i0)")   '    useylm:  ', dtset%useylm
     290            3 :    write(ab_out, "(a, i0)")   '    inclvkb: ', dtset%inclvkb
     291            3 :    write(ab_out, "(2(a, i0))")'    bmin: ', bmin, ", bmax: ", bmax
     292            3 :    if (ds%only_diago) then
     293            0 :      write(ab_out, "(a)")'    Computing diagonal matrix elements only'
     294              :    else
     295            3 :      write(ab_out, "(a)")'    Computing diagonal and off-diagonal matrix elements'
     296              :    end if
     297            3 :    write(ab_out, "(2(a, i0))")'    Between band index bmin: ', bmin, ", bmax: ", bmax
     298            3 :    write(ab_out, "(a)")""
     299              :  end if
     300              : 
     301              :  ! Create distribution of the wavefunctions mask.
     302           12 :  ABI_MALLOC(nband, (nkpt, nsppol))
     303           15 :  ABI_MALLOC(keep_ur, (mband, nkpt, nsppol))
     304           12 :  ABI_MALLOC(bks_mask, (mband, nkpt, nsppol))
     305          702 :  keep_ur = .false.; bks_mask = .false.; nband = mband
     306              : 
     307            3 :  if (ds%only_diago) then
     308              :    ! Distribute k-points, spin and (b, b) diagonal over MPI processors.
     309            0 :    ABI_MALLOC(distrib_diago, (bmin:bmax, nkpt, nsppol))
     310            0 :    distrib_diago = -1
     311              : 
     312              :    ! Create bks_mask to load the wavefunctions.
     313            0 :    ii = 0
     314            0 :    do spin=1,nsppol
     315            0 :      do ik=1,nkpt
     316            0 :        do ib_v=bmin,bmax
     317            0 :           ii = ii + 1; if (mod(ii, nproc) /= my_rank) cycle ! MPI parallelism.
     318            0 :           distrib_diago(ib_v, ik, spin) = my_rank
     319            0 :           bks_mask(ib_v, ik, spin) = .true.
     320              :        end do
     321              :      end do
     322              :    end do
     323            0 :    call wrtout(std_out, sjoin(" Rank: ", itoa(my_rank), "will treat", itoa(count(distrib_diago == my_rank))))
     324              : 
     325              :  else
     326              :    ! Distribute k-points, spin and (b, b') pairs over the processors
     327           18 :    ABI_MALLOC(distrib_mat, (bmin:bmax, bmin:bmax, nkpt, nsppol))
     328            3 :    call xmpi_distab(nproc, distrib_mat)
     329              : 
     330              :    ! Create bks_mask to load the wavefunctions
     331            6 :    do spin=1,nsppol
     332           36 :      do ik=1,nkpt
     333              :        ! Loop over v bands
     334          333 :        do ib_v=bmin,bmax
     335              :         ! Loop over c bands
     336         3330 :          do ib_c=bmin,bmax
     337         3300 :            if (distrib_mat(ib_c, ib_v, ik, spin) == my_rank) then
     338         3000 :              bks_mask(ib_v, ik, spin) = .true.
     339         3000 :              bks_mask(ib_c, ik, spin) = .true.
     340              :            end if
     341              :          end do
     342              :        end do
     343              :      end do
     344              :    end do
     345              : 
     346         3336 :    call wrtout(std_out, sjoin(" Rank: ", itoa(my_rank), "will treat", itoa(count(distrib_mat == my_rank))))
     347              :  end if
     348              : 
     349              :  ! Initialize distributed wavefunctions object
     350              :  call wfd%init(cryst, pawtab, psps, keep_ur, mband, nband, nkpt, nsppol,&
     351              :    bks_mask, dtset%nspden, nspinor, hdr%ecut, dtset%ecutsm, dtset%dilatmx, ebands%istwfk, ebands%kptns,&
     352            3 :    ngfftc, dtset%nloalg, dtset%prtvol, dtset%pawprtvol, comm)
     353              : 
     354            3 :  ABI_FREE(bks_mask)
     355            3 :  ABI_FREE(keep_ur)
     356            3 :  ABI_FREE(nband)
     357              : 
     358            6 :  call wfd%print([std_out], header="Wavefunctions on the k-points grid")
     359              : 
     360              :  ! Read wavefunctions from WFK file.
     361            3 :  call wfd%read_wfk(wfk_path, iomode_from_fname(wfk_path))
     362              : 
     363              :  ! Allocate workspace arrays
     364           33 :  mpw = maxval(wfd%npwarr)
     365            9 :  ABI_MALLOC(kg_k, (3, mpw))
     366            9 :  ABI_MALLOC(ug_c, (mpw*nspinor))
     367            6 :  ABI_MALLOC(ug_v, (mpw*nspinor))
     368            3 :  if (dtset%useria /= 666) then
     369            9 :    ABI_MALLOC(cg_c, (2, mpw*nspinor))
     370            6 :    ABI_MALLOC(cg_v, (2, mpw*nspinor))
     371              :  end if
     372              : 
     373            3 :  ABI_MALLOC(cwaveprj, (0, 0))
     374        27351 :  ABI_CALLOC(ds%dipoles, (3, 2, bmin:bmax, bmin:bmax, nkpt, nsppol))
     375            9 :  ABI_MALLOC(ihrc, (3, nspinor**2))
     376              : 
     377            3 :  if (ds%only_diago) then
     378            0 :    ABI_CALLOC(ds%vdiago, (3, bmin:bmax, nkpt, nsppol))
     379              :  else
     380        30348 :    ABI_CALLOC(ds%vmat, (2, 3, bmin:bmax, bmin:bmax, nkpt, nsppol))
     381              :  end if
     382              : 
     383            3 :  if (dtset%useria /= 666) then
     384            3 :    call ddkop%init(dtset, cryst, pawtab, psps, wfd%mpi_enreg, mpw, wfd%ngfft)
     385              :    !if (my_rank == master) call ddkop%print(ab_out)
     386              :  end if
     387              : 
     388            3 :  call cwtime(cpu_all, wall_all, gflops_all, "start")
     389              : 
     390            6 :  do spin=1,nsppol
     391           36 :    do ik=1,nkpt
     392              : 
     393              :      ! Only do a subset a k-points
     394           30 :      if (ds%only_diago) then
     395            0 :        if (all(distrib_diago(:, ik, spin) /= my_rank)) cycle
     396              :      else
     397           30 :        if (all(distrib_mat(bmin:bmax, bmin:bmax, ik, spin) /= my_rank)) cycle
     398              :      end if
     399           30 :      call cwtime(cpu, wall, gflops, "start")
     400              : 
     401           30 :      nband_k  = wfd%nband(ik, spin)
     402           30 :      istwf_k  = wfd%istwfk(ik)
     403           30 :      npw_k    = wfd%npwarr(ik)
     404          120 :      kpt      = wfd%kibz(:,ik)
     405       138342 :      kg_k(:,1:npw_k) = wfd%kdata(ik)%kg_k
     406              : 
     407           30 :      if (dtset%useria /= 666) then
     408           30 :        call ddkop%setup_spin_kpoint(dtset, cryst, psps, spin, kpt, istwf_k, npw_k, kg_k)
     409              :      else
     410              :        ! Allocate KB form factors
     411              :        ! Prepare term i <n,k|[Vnl,r]|n"k>
     412            0 :        if (dtset%inclvkb /= 0) call vkbr_init(vkbr, cryst, psps, dtset%inclvkb, istwf_k, npw_k, kpt, kg_k)
     413              :      end if
     414              : 
     415              :      ! Loop over bands
     416          330 :      do ib_v=bmin,bmax
     417          300 :        if (ds%only_diago) then
     418            0 :          if (distrib_diago(ib_v,ik,spin) /= my_rank) cycle
     419              :        else
     420          300 :          if (all(distrib_mat(:,ib_v,ik,spin) /= my_rank)) cycle
     421              :        end if
     422              : 
     423          300 :        if (dtset%useria /= 666) then
     424          300 :          call wfd%copy_cg(ib_v, ik, spin, cg_v)
     425          300 :          call ddkop%apply(ebands%eig(ib_v, ik, spin), npw_k, wfd%nspinor, cg_v, cwaveprj)
     426              :        else
     427            0 :          ABI_CHECK(wfd%get_wave_ptr(ib_v, ik, spin, wave_v, msg) == 0, msg)
     428            0 :          ug_v(1:npw_k*nspinor) = wave_v%ug
     429              :        end if
     430              : 
     431              :        ! Loop over bands
     432          300 :        bstop = bmax; if (ds%only_diago) bstop = ib_v
     433         1980 :        do ib_c=ib_v,bstop
     434         1650 :          if (.not. ds%only_diago) then
     435         1650 :            if (distrib_mat(ib_c, ib_v, ik, spin) /= my_rank) cycle
     436              :          end if
     437              : 
     438         1950 :          if (dtset%useria /= 666) then
     439         1650 :            call wfd%copy_cg(ib_c, ik, spin, cg_c)
     440         1650 :            vv = ddkop%get_braket(ebands%eig(ib_c, ik, spin), istwf_k, npw_k, nspinor, cg_c, mode=ds%mode)
     441              :            !if (ib_v == ib_c) vv(2, :) = zero
     442              : 
     443         1650 :            if (ds%only_diago) then
     444            0 :              ds%vdiago(:,ib_c,ik,spin) = vv(1, :)
     445              :            else
     446        16500 :              ds%vmat(:,:,ib_c,ib_v,ik,spin) = vv
     447              :              ! Hermitian conjugate
     448         1650 :              if (ib_v /= ib_c) then
     449         5400 :                ds%vmat(1,:,ib_v,ib_c,ik,spin) =  vv(1, :)
     450         5400 :                ds%vmat(2,:,ib_v,ib_c,ik,spin) = -vv(2, :)
     451              :              end if
     452              :            end if
     453              : 
     454         6600 :            do idir=1,3
     455        14850 :              ds%dipoles(idir,:,ib_c,ib_v,ik,spin) = vv(:, idir)
     456              :              ! Hermitian conjugate
     457        14700 :              if (ib_v /= ib_c) ds%dipoles(idir,:,ib_v,ib_c,ik,spin) = [vv(1, idir), -vv(2, idir)]
     458              :            end do
     459              : 
     460              :          else
     461            0 :            ABI_CHECK(wfd%get_wave_ptr(ib_c, ik, spin, wave_c, msg) == 0, msg)
     462            0 :            ug_c(1:npw_k*nspinor) = wave_c%ug
     463              : 
     464              :            ! Calculate matrix elements of i[H,r] for NC pseudopotentials.
     465            0 :            ihrc = nc_ihr_comm(vkbr, cryst, psps, npw_k, nspinor, istwf_k, dtset%inclvkb, kpt, ug_c, ug_v, kg_k)
     466              : 
     467              :            ! HM: 24/07/2018
     468              :            ! Transform dipoles to be consistent with results from DFPT
     469              :            ! Perturbations with DFPT are along the reciprocal lattice vectors
     470              :            ! Perturbations with Commutator are along real space lattice vectors
     471              :            ! dot(A, DFPT) = X
     472              :            ! dot(B, COMM) = X
     473              :            ! B = 2 pi (A^{-1})^T =>
     474              :            ! dot(B^T B,COMM) = 2 pi DFPT
     475            0 :            vr = (2*pi)*(2*pi)*sum(ihrc(:,:),dim=2)
     476            0 :            vg(1) = dot_product(Cryst%gmet(1,:), vr)
     477            0 :            vg(2) = dot_product(Cryst%gmet(2,:), vr)
     478            0 :            vg(3) = dot_product(Cryst%gmet(3,:), vr)
     479              : 
     480              :            ! Save matrix elements of i*r in the IBZ
     481            0 :            ds%dipoles(:,1,ib_c,ib_v,ik,spin) = real(vg, kind=dp)
     482            0 :            ds%dipoles(:,1,ib_v,ib_c,ik,spin) = real(vg, kind=dp) ! Hermitian conjugate
     483            0 :            if (ib_v == ib_c) then
     484            0 :              ds%dipoles(:,2,ib_c,ib_v,ik,spin) = zero
     485            0 :              ds%dipoles(:,2,ib_v,ib_c,ik,spin) = zero
     486              :            else
     487            0 :              ds%dipoles(:,2,ib_c,ib_v,ik,spin) =  aimag(vg)
     488            0 :              ds%dipoles(:,2,ib_v,ib_c,ik,spin) = -aimag(vg) ! Hermitian conjugate
     489              :            end if
     490              :          end if
     491              : 
     492              :        end do
     493              :      end do
     494              : 
     495              :      ! Free KB form factors
     496           30 :      call vkbr_free(vkbr)
     497              : 
     498           63 :      if (nkpt < 1000 .or. (nkpt > 1000 .and. mod(ik, 200) == 0) .or. ik <= nproc) then
     499           30 :        write(msg,'(2(a,i0),a)')" k-point [", ik, "/", nkpt, "]"
     500           30 :        call cwtime_report(msg, cpu, wall, gflops)
     501              :      end if
     502              : 
     503              :    end do ! k-points
     504              :  end do ! spin
     505              : 
     506            3 :  call cwtime_report(msg, cpu_all, wall_all, gflops_all)
     507              : 
     508            3 :  ABI_FREE(ug_c)
     509            3 :  ABI_FREE(ug_v)
     510            3 :  ABI_FREE(kg_k)
     511            3 :  ABI_FREE(ihrc)
     512            3 :  ABI_FREE(cwaveprj)
     513            3 :  ABI_SFREE(distrib_mat)
     514            3 :  ABI_SFREE(distrib_diago)
     515              : 
     516            3 :  if (dtset%useria /= 666) then
     517            3 :    ABI_FREE(cg_c)
     518            3 :    ABI_FREE(cg_v)
     519            3 :    call ddkop%free()
     520              :  end if
     521              : 
     522              :  ! Gather the k-points computed by all processes
     523            3 :  call xmpi_sum_master(ds%dipoles, master, comm, ierr)
     524              : 
     525            3 :  if (ds%only_diago) then
     526            0 :    call xmpi_sum_master(ds%vdiago, master, comm, ierr)
     527              :  else
     528            3 :    call xmpi_sum_master(ds%vmat, master, comm, ierr)
     529              :  end if
     530              : 
     531              :  ! Write matrix elements to disk.
     532              : 
     533              :  ! Output EVK file in netcdf format.
     534            3 :  if (my_rank == master .and. write_ncfile .and. dtset%prtevk == 1) then
     535              :    ! Have to build hdr on k-grid with info about perturbation.
     536            0 :    call hdr%copy(tmp_hdr)
     537            0 :    tmp_hdr%qptn = zero
     538              : 
     539              :    !fname = strcat(prefix, "NEW_EVK.nc")
     540              :    !call wrtout(ab_out, sjoin("- Writing file: ", fname))
     541              :    !NCF_CHECK_MSG(nctk_open_create(ncid, fname, xmpi_comm_self), "Creating EVK.nc file")
     542              :    !tmp_hdr%pertcase = 0
     543              :    !NCF_CHECK(tmp_hdr%ncwrite(ncid, 43, nc_define=.True.))
     544              :    !NCF_CHECK(cryst%ncwrite(ncid))
     545              :    !NCF_CHECK(ebands%ncwrite(ncid))
     546              :    !if (ds%only_diago) then
     547              :    !  ncerr = nctk_def_arrays(ncid, [ &
     548              :    !    nctkarr_t('vred_diagonal', "dp", "three, max_number_of_states, number_of_kpoints, number_of_spins")], defmode=.True.)
     549              :    !else
     550              :    !  ncerr = nctk_def_arrays(ncid, [ nctkarr_t('vred_matrix', "dp", &
     551              :    !      "two, three, max_number_of_states, max_number_of_states, number_of_kpoints, number_of_spins")], defmode=.True.)
     552              :    !end if
     553              :    !NCF_CHECK(ncerr)
     554              :    !NCF_CHECK(nctk_set_datamode(ncid))
     555              :    !if (ds%only_diago) then
     556              :    !  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vred_diagonal"), ds%vdiago))
     557              :    !else
     558              :    !  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vred_matrix"), ds%vmat))
     559              :    !end if
     560              :    !NCF_CHECK(nf90_close(ncid))
     561              : 
     562            0 :    do ii=1,3
     563            0 :      fname = strcat(prefix, '_', itoa(ii), "_EVK.nc")
     564            0 :      call wrtout(ab_out, sjoin("- Writing EVK file: ", fname, "for reduced direction:", itoa(ii)))
     565            0 :      NCF_CHECK_MSG(nctk_open_create(ncid, fname, xmpi_comm_self), "Creating EVK.nc file")
     566            0 :      tmp_hdr%pertcase = 3 * cryst%natom + ii
     567            0 :      NCF_CHECK(tmp_hdr%ncwrite(ncid, 43, nc_define=.True.))
     568            0 :      NCF_CHECK(cryst%ncwrite(ncid))
     569            0 :      NCF_CHECK(ebands%ncwrite(ncid))
     570              :      ncerr = nctk_def_arrays(ncid, [ &
     571              :        nctkarr_t('h1_matrix_elements', "dp", &
     572            0 :         "two, max_number_of_states, max_number_of_states, number_of_kpoints, number_of_spins")], defmode=.True.)
     573            0 :      NCF_CHECK(ncerr)
     574            0 :      NCF_CHECK(nctk_set_datamode(ncid))
     575            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "h1_matrix_elements"), ds%dipoles(ii,:,:,:,:,:)))
     576            0 :      NCF_CHECK(nf90_close(ncid))
     577              :    end do
     578            0 :    call tmp_hdr%free()
     579              :  end if
     580              : 
     581            3 :  if (my_rank == master .and. dtset%prtvol > 0) then
     582            3 :    write(ab_out, "(2a)")ch10,"Writing velocity matrix elements (only diagonal terms, real part) for testing purpose:"
     583            6 :    do spin=1,nsppol
     584           18 :      do ik=1,min(nkpt, 4)
     585           12 :        write(ab_out, "(2(a,1x,i0),2x,2a)")"For spin: ", spin, ", ikbz: ", ik, ", kpt: ", trim(ktoa(wfd%kibz(:,ik)))
     586          120 :        do ib_c=bmin,min(bmin+8, bmax)
     587          120 :          write(ab_out, "(3(es16.6,2x))") ds%dipoles(:,1,ib_c,ib_c,ik,spin)
     588              :        end do
     589           15 :        write(ab_out,*)""
     590              :        !do ib_c=bmin,min(bmin+8, bmax)
     591              :        !  write(ab_out, "(a, 6(es16.6,2x))")"Sum_k: ", sum(ds%dipoles(:,:,ib_c,ib_c,:,spin), dim=3) / nkpt
     592              :        !end do
     593              :      end do
     594              :    end do
     595              :  end if
     596              : 
     597              :  ! Free memory
     598            3 :  call wfd%free()
     599            3 :  call ebands%free()
     600            3 :  call cryst%free()
     601            3 :  call hdr%free()
     602              : 
     603              :  ! Block all procs here so that we know output files are available when code returns.
     604            3 :  call xmpi_barrier(comm)
     605              : 
     606           39 : end subroutine ddkstore_compute_ddk
     607              : !!***
     608              : 
     609              : !----------------------------------------------------------------------
     610              : 
     611              : !!****f* m_ddk/ddkstore_free
     612              : !! NAME
     613              : !!  ddkstore_free
     614              : !!
     615              : !! FUNCTION
     616              : !!  Free memory
     617              : !!
     618              : !! INPUTS
     619              : !!
     620              : !! SOURCE
     621              : 
     622            3 : subroutine ddkstore_free(self)
     623              : 
     624              : !Arguments ------------------------------------
     625              :  class(ddkstore_t),intent(inout) :: self
     626              : !************************************************************************
     627              : 
     628            3 :  ABI_SFREE(self%vdiago)
     629            3 :  ABI_SFREE(self%vmat)
     630            3 :  ABI_SFREE(self%dipoles)
     631              : 
     632            3 : end subroutine ddkstore_free
     633              : !!***
     634              : 
     635              : !----------------------------------------------------------------------
     636              : 
     637              : !!****f* m_ddk/ddk_red2car
     638              : !! NAME
     639              : !!  ddk_red2car
     640              : !!
     641              : !! FUNCTION
     642              : !!  Convert ddk matrix element from reduced coordinates to cartesian coordinates.
     643              : !!
     644              : !! SOURCE
     645              : 
     646         1388 : pure subroutine ddk_red2car(rprimd, vred, vcar)
     647              : 
     648              : !Arguments -------------------------------------
     649              :  real(dp),intent(in) :: rprimd(3,3)
     650              :  real(dp),intent(in) :: vred(2,3)
     651              :  real(dp),intent(out) :: vcar(2,3)
     652              : 
     653              : !Local variables -------------------------------
     654              :  real(dp) :: vtmp(2,3)
     655              : !************************************************************************
     656              : 
     657              :  ! Go to Cartesian coordinates (same as pmat2cart routine)
     658              :  ! V_cart = 1/(2pi) * Rprimd x V_red
     659              :  ! where V_red is the derivative computed in the DFPT routines (derivative wrt reduced component).
     660              :  vtmp(1,:) = rprimd(:,1)*vred(1,1) &
     661              :             +rprimd(:,2)*vred(1,2) &
     662         5552 :             +rprimd(:,3)*vred(1,3)
     663              :  vtmp(2,:) = rprimd(:,1)*vred(2,1) &
     664              :             +rprimd(:,2)*vred(2,2) &
     665         5552 :             +rprimd(:,3)*vred(2,3)
     666        13880 :  vcar = vtmp / two_pi
     667              : 
     668         1388 : end subroutine ddk_red2car
     669              : !!***
     670              : 
     671              : !----------------------------------------------------------------------
     672              : 
     673              : !!****f* m_ddk/ddkop_init
     674              : !! NAME
     675              : !!  ddkop_init
     676              : !!
     677              : !! FUNCTION
     678              : !!  Build new object. Use dtset%inclvkb to determine whether the non-local part should be included.
     679              : !!
     680              : !! INPUTS
     681              : !! dtset<dataset_type>=All input variables for this dataset.
     682              : !! cryst<crystal_t>=Crystal structure.
     683              : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
     684              : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
     685              : !! mpi_enreg=information about MPI parallelization
     686              : !! mpw=Maximum number of plane-waves over k-points.
     687              : !! ngfft(18)=contain all needed information about 3D FFT
     688              : !!
     689              : !! SOURCE
     690              : 
     691           74 : subroutine ddkop_init(ddkop, dtset, cryst, pawtab, psps, mpi_enreg, mpw, ngfft)
     692              : 
     693              : !Arguments ------------------------------------
     694              : !scalars
     695              :  class(ddkop_t),intent(out) :: ddkop
     696              :  type(dataset_type),intent(in) :: dtset
     697              :  type(crystal_t),intent(in) :: cryst
     698              :  type(pseudopotential_type),intent(in) :: psps
     699              :  type(MPI_type),target,intent(in) :: mpi_enreg
     700              :  integer,intent(in) :: mpw
     701              : !arrays
     702              :  integer,intent(in) :: ngfft(18)
     703              :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
     704              : 
     705              : !Local variables-------------------------------
     706              : !scalars
     707              :  integer,parameter :: cplex1 = 1
     708              :  integer :: nfft, mgfft, idir
     709              : ! *************************************************************************
     710              : 
     711           74 :  ABI_CHECK(dtset%usepaw == 0, "PAW not tested/implemented!")
     712              : 
     713           74 :  ddkop%inclvkb = dtset%inclvkb
     714           74 :  ddkop%usepaw = dtset%usepaw
     715           74 :  ddkop%ipert = cryst%natom + 1
     716           74 :  ddkop%dfpt_sciss = dtset%dfpt_sciss
     717           74 :  ddkop%mpw = mpw
     718              : 
     719          962 :  ddkop%rprimd = cryst%rprimd
     720           74 :  ddkop%mpi_enreg => mpi_enreg
     721              : 
     722              :  ! Not used because vlocal1 is not applied.
     723          296 :  nfft = product(ngfft(1:3))
     724          296 :  mgfft = maxval(ngfft(1:3))
     725              : 
     726          296 :  do idir=1,3
     727              :    ! ==== Initialize most of the Hamiltonian (and derivative) ====
     728              :    ! 1) Allocate all arrays and initialize quantities that do not depend on k and spin.
     729              :    ! 2) Perform the setup needed for the non-local factors:
     730              :    ! * Norm-conserving: Constant kleimann-Bylander energies are copied from psps to gs_hamk.
     731              :    ! * PAW: Initialize the overlap coefficients and allocate the Dij coefficients.
     732              :    call ddkop%gs_hamkq(idir)%init(psps, pawtab, dtset%nspinor, dtset%nsppol, dtset%nspden, cryst%natom,&
     733              :      cryst%typat, cryst%xred, nfft, mgfft, ngfft, cryst%rprimd, dtset%nloalg &
     734          222 :      )
     735              :      !paw_ij=paw_ij,comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab,mpi_spintab=mpi_enreg%my_isppoltab,&
     736              :      !usecprj=usecprj,ph1d=ph1d,nucdipmom=dtset%nucdipmom,
     737              :      ! TODO
     738              :      !gpu_option=dtset%gpu_option)
     739              : 
     740              :    ! Prepare application of the NL part.
     741          296 :    call ddkop%rf_hamkq(idir)%init(cplex1, ddkop%gs_hamkq(idir), ddkop%ipert, has_e1kbsc=.true.)
     742              :  end do
     743              : 
     744           74 : end subroutine ddkop_init
     745              : !!***
     746              : 
     747              : !----------------------------------------------------------------------
     748              : 
     749              : !!****f* m_ddk/ddkop_setup_spin_kpoint
     750              : !! NAME
     751              : !!  ddkop_setup_spin_kpoint
     752              : !!
     753              : !! FUNCTION
     754              : !!  Prepare internal tables that depend on k-point/spin
     755              : !!
     756              : !! INPUTS
     757              : !!  dtset<dataset_type>=All input variables for this dataset.
     758              : !!  cryst<crystal_t>=Crystal structure.
     759              : !!  psps<pseudopotential_type>=Variables related to pseudopotentials.
     760              : !!  spin: spin index
     761              : !!  kpoint(3): K-point in reduced coordinates.
     762              : !!  istwkf_k: defines storage of wavefunctions for this k-point
     763              : !!  npw_k: Number of planewaves.
     764              : !!  kg_k(3,npw_k)=reduced planewave coordinates.
     765              : !!
     766              : !! SOURCE
     767              : 
     768          361 : subroutine ddkop_setup_spin_kpoint(ddkop, dtset, cryst, psps, spin, kpoint, istwf_k, npw_k, kg_k)
     769              : 
     770              : !Arguments ------------------------------------
     771              : !scalars
     772              :  class(ddkop_t),intent(inout) :: ddkop
     773              :  type(dataset_type),intent(in) :: dtset
     774              :  type(crystal_t),intent(in) :: cryst
     775              :  type(pseudopotential_type),intent(in) :: psps
     776              :  integer,intent(in) :: spin, npw_k, istwf_k
     777              : !arrays
     778              :  integer,intent(in) :: kg_k(3,npw_k)
     779              :  real(dp),intent(in) :: kpoint(3)
     780              : 
     781              : !Local variables-------------------------------
     782              : !scalars
     783              :  integer,parameter :: nkpt1=1, nsppol1=1
     784          361 :  type(mpi_type) :: mpienreg_seq
     785              : !arrays
     786              :  integer :: npwarr(nkpt1), dummy_nband(nkpt1*nsppol1)
     787              :  integer :: idir, nkpg, nkpg1, useylmgr1, optder !, nylmgr1
     788          361 :  real(dp),allocatable :: ylm_k(:,:),ylmgr1_k(:,:,:)
     789              : !************************************************************************
     790              : 
     791          361 :  ABI_CHECK_ILEQ(npw_k, ddkop%mpw, "npw_k > mpw!")
     792         1444 :  ddkop%kpoint = kpoint
     793              : 
     794              :  ! Set up the spherical harmonics (Ylm) at k+q if useylm = 1
     795          361 :  useylmgr1 = 0; optder = 0
     796          361 :  if (psps%useylm == 1) then
     797           18 :    useylmgr1 = 1; optder = 1
     798              :  end if
     799              : 
     800      2027986 :  ABI_RECALLOC(ddkop%gh1c, (2, npw_k*dtset%nspinor, 3))
     801      2027264 :  ABI_RECALLOC(ddkop%gs1c, (2, npw_k*dtset%nspinor, 3))
     802              : 
     803         1444 :  ABI_MALLOC(ylm_k, (npw_k, psps%mpsang**2 * psps%useylm))
     804         1805 :  ABI_MALLOC(ylmgr1_k, (npw_k, 3+6*(optder/2), psps%mpsang**2*psps%useylm*useylmgr1))
     805              : 
     806          361 :  if (psps%useylm == 1) then
     807              :    ! Fake MPI_type for sequential part. dummy_nband and nsppol1 are not used in sequential mode.
     808           18 :    call initmpi_seq(mpienreg_seq)
     809           36 :    dummy_nband = 0; npwarr = npw_k
     810              :    call initylmg(cryst%gprimd, kg_k, kpoint, nkpt1, mpienreg_seq, psps%mpsang, npw_k, dummy_nband, nkpt1, &
     811           18 :       npwarr, nsppol1, optder, cryst%rprimd, ylm_k, ylmgr1_k)
     812           18 :    call destroy_mpi_enreg(mpienreg_seq)
     813              :  end if
     814              : 
     815         1444 :  do idir=1,3
     816         1083 :    call ddkop%htg(idir)%free()
     817              : 
     818              :    ! Continue to initialize the Hamiltonian
     819         1083 :    call ddkop%gs_hamkq(idir)%load_spin(spin, with_nonlocal=.true.)
     820         1083 :    call ddkop%rf_hamkq(idir)%load_spin(spin, with_nonlocal=.true.)
     821              : 
     822              :    ! We need ffnl1 and dkinpw for 3 dirs. Note that the Hamiltonian objects use pointers to keep a reference
     823              :    ! to the output results of this routine.
     824              :    ! This is the reason why we need to store the targets in ddkop%htg
     825              :    call getgh1c_setup(ddkop%gs_hamkq(idir), ddkop%rf_hamkq(idir), dtset, psps, kpoint, kpoint, idir, ddkop%ipert, & ! In
     826              :      cryst%natom, cryst%rmet, cryst%gprimd, cryst%gmet, istwf_k, npw_k, npw_k, &            ! In
     827              :      useylmgr1, kg_k, ylm_k, kg_k, ylm_k, ylmgr1_k, &                                       ! In
     828              :      ddkop%htg(idir)%dkinpw, nkpg, nkpg1, ddkop%htg(idir)%kpg_k, ddkop%htg(idir)%kpg1_k, &  ! Out
     829              :      ddkop%htg(idir)%kinpw1, ddkop%htg(idir)%ffnlk, ddkop%htg(idir)%ffnl1, &                ! Out
     830         1444 :      ddkop%htg(idir)%ph3d, ddkop%htg(idir)%ph3d1)                                           ! Out
     831              :  end do
     832              : 
     833          361 :  ABI_FREE(ylm_k)
     834          361 :  ABI_FREE(ylmgr1_k)
     835              : 
     836          361 : end subroutine ddkop_setup_spin_kpoint
     837              : !!***
     838              : 
     839              : !----------------------------------------------------------------------
     840              : 
     841              : !!****f* m_ddk/ddkop_apply
     842              : !! NAME
     843              : !!  ddkop_apply
     844              : !!
     845              : !! FUNCTION
     846              : !!  Apply velocity operator dH/dk to wavefunction in G-space. Store results in object.
     847              : !!
     848              : !! INPUTS
     849              : !!  eig0nk: Eigenvalue associated to the wavefunction.
     850              : !!  npw_k: Number of planewaves.
     851              : !!  nspinor: Number of spinor components.
     852              : !!  cwave(2,npw_k*nspinor)=input wavefunction in reciprocal space
     853              : !!  cwaveprj(natom,nspinor*usecprj)=<p_lmn|C> coefficients for wavefunction |C> (and 1st derivatives)
     854              : !!     if not allocated or size=0, they are locally computed (and not sorted)!!
     855              : !!
     856              : !! SIDE EFFECTS
     857              : !! Stores:
     858              : !!  gh1c(2,npw_k*nspinor)= <G|H^(1)|C> or <G|H^(1)-lambda.S^(1)|C> on the k+q sphere
     859              : !!                        (only kinetic+non-local parts if optlocal=0)
     860              : !!
     861              : !! SOURCE
     862              : 
     863         1688 : subroutine ddkop_apply(ddkop, eig0nk, npw_k, nspinor, cwave, cwaveprj)
     864              : 
     865              : !Arguments ------------------------------------
     866              : !scalars
     867              :  class(ddkop_t),target,intent(inout) :: ddkop
     868              :  integer,intent(in) :: npw_k, nspinor
     869              :  real(dp),intent(in) :: eig0nk
     870              : !arrays
     871              :  real(dp),intent(inout) :: cwave(2,npw_k*nspinor)
     872              :  type(pawcprj_type),intent(inout) :: cwaveprj(:,:)
     873              : 
     874              : !Local variables-------------------------------
     875              : !scalars
     876              :  integer,parameter :: berryopt0 = 0, optlocal0 = 0, tim_getgh1c = 1, usevnl0 = 0, opt_gvnlx1 = 0
     877              :  integer :: idir, sij_opt, ispinor, ipws, ipw, optnl
     878              :  real(dp) :: eshift
     879              : !arrays
     880              :  real(dp) :: grad_berry(2,(berryopt0/4)), gvnlx1(2,usevnl0)
     881              : !************************************************************************
     882              : 
     883         1688 :  ddkop%eig0nk = eig0nk
     884              : 
     885         1688 :  if (ddkop%inclvkb /= 0) then
     886              :  !if (.True.) then
     887              :    ! optlocal0 = 0: local part of H^(1) is not computed in gh1c=<G|H^(1)|C>
     888              :    ! optnl = 2: non-local part of H^(1) is totally computed in gh1c=<G|H^(1)|C>
     889              :    ! opt_gvnlx1 = option controlling the use of gvnlx1 array:
     890         1588 :    optnl = 2; if (ddkop%inclvkb == 0) optnl = 0
     891              : 
     892         1588 :    eshift = ddkop%eig0nk - ddkop%dfpt_sciss
     893         6352 :    do idir=1,3
     894         4764 :      sij_opt = ddkop%gs_hamkq(idir)%usepaw
     895              :      call getgh1c(berryopt0, cwave, cwaveprj, ddkop%gh1c(:,:,idir), &
     896              :        grad_berry, ddkop%gs1c(:,:,idir), ddkop%gs_hamkq(idir), gvnlx1, idir, ddkop%ipert, [eshift], ddkop%mpi_enreg, 1, optlocal0, &
     897        11116 :        optnl, opt_gvnlx1, ddkop%rf_hamkq(idir), sij_opt, tim_getgh1c, usevnl0)
     898              :    end do
     899              : 
     900              :  else
     901              :    ! FIXME: optnl 0 with DDK does not work as expected.
     902              :    ! So I treat the kinetic term explicitly without calling getgh1c.
     903          400 :    do idir=1,3
     904          100 :      associate (kinpw1 => ddkop%gs_hamkq(idir)%kinpw_kp, dkinpw => ddkop%rf_hamkq(idir)%dkinpw_k)
     905          600 :      do ispinor=1,nspinor
     906       346380 :        do ipw=1,npw_k
     907       345780 :          ipws = ipw + npw_k*(ispinor-1)
     908       346080 :          if (kinpw1(ipw) < huge(zero)*1.d-11) then
     909      1037340 :            ddkop%gh1c(:,ipws,idir) = dkinpw(ipw) * cwave(:,ipws)
     910              :          else
     911            0 :            ddkop%gh1c(:,ipws,idir) = zero
     912              :          end if
     913              :        end do
     914              :      end do
     915              :      end associate
     916              :    end do ! idir
     917              :  end if
     918              : 
     919         1688 : end subroutine ddkop_apply
     920              : !!***
     921              : 
     922              : !----------------------------------------------------------------------
     923              : 
     924              : !!****f* m_ddk/ddkop_get_braket
     925              : !! NAME
     926              : !!  ddkop_get_braket
     927              : !!
     928              : !! FUNCTION
     929              : !!  Compute diagonal matrix element in Cartesian coordinates.
     930              : !!
     931              : !! INPUTS
     932              : !!  eig0mk: Eigenvalue associated to the "bra" wavefunction
     933              : !!  istwkf_k: defines storage of wavefunctions for this k-point
     934              : !!  npw_k: Number of planewaves.
     935              : !!  nspinor: Number of spinor components.
     936              : !!  brag(2,npw_k*nspinor)=input wavefunction in reciprocal space
     937              : !!
     938              : !! SOURCE
     939              : 
     940         6076 : function ddkop_get_braket(ddkop, eig0mk, istwf_k, npw_k, nspinor, brag, mode) result(vk)
     941              : 
     942              : !Arguments ------------------------------------
     943              : !scalars
     944              :  class(ddkop_t),intent(in) :: ddkop
     945              :  integer,intent(in) :: istwf_k, npw_k, nspinor
     946              :  real(dp),intent(in) :: eig0mk
     947              :  character(len=*),optional,intent(in) :: mode
     948              : !arrays
     949              :  real(dp),intent(in) :: brag(2*npw_k*nspinor)
     950              :  real(dp) :: vk(2,3)
     951              : 
     952              : !Local variables-------------------------------
     953              : !scalars
     954              :  integer :: idir
     955              :  real(dp) :: doti
     956              : !arrays
     957              :  real(dp) :: dotarr(2), vk_red(2, 3)
     958              :  character(len=50) :: my_mode
     959              : !************************************************************************
     960              : 
     961         3038 :  if (ddkop%usepaw == 0) then
     962              :    ! <u_(iband,k+q)^(0)|H_(k+q,k)^(1)|u_(jband,k)^(0)>  (NC psps)
     963        12152 :    do idir=1,3
     964         9114 :      dotarr = cg_zdotc(npw_k * nspinor, brag, ddkop%gh1c(:,:,idir))
     965         9114 :      if (istwf_k > 1) then
     966              :        !dum = two * j_dpc * AIMAG(dum); if (vkbr%istwfk==2) dum = dum - j_dpc * AIMAG(gamma_term)
     967            0 :        doti = two * dotarr(2)
     968            0 :        if (istwf_k == 2 .and. ddkop%mpi_enreg%me_g0 == 1) then
     969              :          ! nspinor always 1
     970              :          ! TODO: Recheck this part but it should be ok.
     971            0 :          doti = doti - (brag(1) * ddkop%gh1c(2,1,idir) - brag(2) * ddkop%gh1c(1,1,idir))
     972              :        end if
     973            0 :        dotarr(2) = doti; dotarr(1) = zero
     974              :      end if
     975        30380 :      vk(:, idir) = dotarr
     976              :    end do
     977              :  else
     978            0 :    ABI_ERROR("PAW Not Implemented")
     979              :    ! <u_(iband,k+q)^(0)|H_(k+q,k)^(1)-(eig0_k+eig0_k+q)/2.S^(1)|u_(jband,k)^(0)> (PAW)
     980              :    ! eshiftkq = half * (eig0mk - ddkop%eig0nk)
     981              :    ABI_UNUSED(eig0mk)
     982              :  end if
     983              : 
     984         3038 :  my_mode = "cart"; if (present(mode)) my_mode = mode
     985              :  select case (mode)
     986              :  case ("cart")
     987        13880 :    vk_red = vk
     988         1388 :    call ddk_red2car(ddkop%rprimd, vk_red, vk)
     989              :  case ("reduced")
     990            0 :    continue
     991              :  case default
     992         3038 :    ABI_ERROR(sjoin("Invalid vaue for mode:", mode))
     993              :  end select
     994              : 
     995         3038 : end function ddkop_get_braket
     996              : !!***
     997              : 
     998              : !----------------------------------------------------------------------
     999              : 
    1000              : !!****f* m_ddk/ddkop_get_ihr_comm
    1001              : !! NAME
    1002              : !!  ddkop_get_ihr_comm
    1003              : !!
    1004              : !! FUNCTION
    1005              : !!  Compute matrix element in Cartesian coordinates.
    1006              : !!
    1007              : !! INPUTS
    1008              : !!  eig0mk: Eigenvalue associated to the "bra" wavefunction
    1009              : !!  istwkf_k: defines storage of wavefunctions for this k-point
    1010              : !!  npw_k: Number of planewaves.
    1011              : !!  nspinor: Number of spinor components.
    1012              : !!  brag(2,npw_k*nspinor)=input wavefunction in reciprocal space
    1013              : !!
    1014              : !! SOURCE
    1015              : 
    1016            0 : subroutine ddkop_get_ihr_comm(ddkop, cryst, eig0mk, istwf_k, npw_k, nspinor, brag, new_rhotwx)
    1017              : 
    1018              : !Arguments ------------------------------------
    1019              : !scalars
    1020              :  class(ddkop_t),intent(in) :: ddkop
    1021              :  type(crystal_t),intent(in) :: cryst
    1022              :  integer,intent(in) :: istwf_k, npw_k, nspinor
    1023              :  real(dp),intent(in) :: eig0mk
    1024              : !arrays
    1025              :  real(dp),intent(in) :: brag(2,npw_k*nspinor)
    1026              :  complex(gwp),intent(out) :: new_rhotwx(3, nspinor**2)
    1027              : 
    1028              : !Local variables-------------------------------
    1029              : !scalars
    1030              :  integer :: idir, iab
    1031              :  real(dp) :: doti
    1032              : !arrays
    1033              :  integer :: spinor_pad(2,4), spad1, spad2 !, rtmp(2)
    1034              :  real(dp) :: dotarr(2)
    1035              : !  real(dp), allocatable :: cg2_dp(:,:),  ddk_ug1(:,:,:)
    1036              : !************************************************************************
    1037              : 
    1038            0 :  spinor_pad = reshape([0, 0, npw_k, npw_k, 0, npw_k, npw_k, 0], [2, 4])
    1039              : 
    1040            0 :  if (ddkop%usepaw == 0) then
    1041              :    ! <u_(iband,k+q)^(0)|H_(k+q,k)^(1)|u_(jband,k)^(0)>  (NC psps)
    1042            0 :    do iab=1,nspinor**2
    1043            0 :      spad1 = spinor_pad(1,iab); spad2 = spinor_pad(2,iab)
    1044            0 :      do idir=1,3
    1045            0 :        dotarr = cg_zdotc(npw_k, brag(:,spad2+1), ddkop%gh1c(:,spad1+1,idir))
    1046            0 :        if (istwf_k > 1) then
    1047            0 :          doti = two * dotarr(2)
    1048            0 :          if (istwf_k == 2 .and. ddkop%mpi_enreg%me_g0 == 1) then
    1049              :            ! nspinor always 1
    1050              :            ! TODO: Recheck this part but it should be ok.
    1051            0 :            doti = doti - (brag(1,1) * ddkop%gh1c(2,1,idir) - brag(2,1) * ddkop%gh1c(1,1,idir))
    1052              :          end if
    1053            0 :          dotarr(2) = doti; dotarr(1) = zero
    1054              :        end if
    1055            0 :        new_rhotwx(idir, iab) = dotarr(1) + j_dpc * dotarr(2)
    1056              :      end do
    1057              :    end do ! iab
    1058              :  else
    1059            0 :    ABI_ERROR("PAW Not Implemented")
    1060              :    ! <u_(iband,k+q)^(0)|H_(k+q,k)^(1)-(eig0_k+eig0_k+q)/2.S^(1)|u_(jband,k)^(0)> (PAW)
    1061              :    ! eshiftkq = half * (eig0mk - ddkop%eig0nk)
    1062              :    ABI_UNUSED(eig0mk)
    1063              :  end if
    1064              : 
    1065              :  ! HM: 24/07/2018
    1066              :  ! Transform dipoles to be consistent with results from DFPT
    1067              :  ! Perturbations with DFPT are along the reciprocal lattice vectors
    1068              :  ! Perturbations with commutator are along real space lattice vectors
    1069              :  ! dot(A, DFPT) = X
    1070              :  ! dot(B, COMM) = X
    1071              :  ! B = 2 pi (A^{-1})^T => dot(B^T B,COMM) = 2 pi DFPT
    1072              : 
    1073            0 :  do iab=1,nspinor**2
    1074            0 :    new_rhotwx(:, iab) = matmul(cryst%rmet, new_rhotwx(:, iab)) / (two_pi ** 2)
    1075              :  end do
    1076              : 
    1077            0 : end subroutine ddkop_get_ihr_comm
    1078              : !!***
    1079              : 
    1080              : !----------------------------------------------------------------------
    1081              : 
    1082              : !!****f* m_ddk/ddkop_get_vdiag
    1083              : !! NAME
    1084              : !!  ddkop_get_vdiag
    1085              : !!
    1086              : !! FUNCTION
    1087              : !!  Simplified interface to compute the diagonal matrix element of the velocity operator in cartesian coords.
    1088              : !!
    1089              : !! INPUTS
    1090              : !!
    1091              : !! SOURCE
    1092              : 
    1093         1388 : function ddkop_get_vdiag(ddkop, eig0nk, istwf_k, npw_k, nspinor, cwave, cwaveprj, mode) result(vk)
    1094              : 
    1095              : !Arguments ------------------------------------
    1096              : !scalars
    1097              :  class(ddkop_t),intent(inout) :: ddkop
    1098              :  integer,intent(in) :: istwf_k, npw_k, nspinor
    1099              :  real(dp),intent(in) :: eig0nk
    1100              :  character(len=*),optional,intent(in) :: mode
    1101              : !arrays
    1102              :  real(dp),intent(inout) :: cwave(2,npw_k*nspinor)
    1103              :  type(pawcprj_type),intent(inout) :: cwaveprj(:,:)
    1104              :  real(dp) :: vk(3)
    1105              : 
    1106              : !Local variables-------------------------------
    1107              :  character(len=50) :: my_mode
    1108              : !arrays
    1109              :  real(dp) :: cvk(2, 3)
    1110              : !************************************************************************
    1111              : 
    1112         1388 :  my_mode = "cart"; if (present(mode)) my_mode = mode
    1113         1388 :  call ddkop%apply(eig0nk, npw_k, nspinor, cwave, cwaveprj)
    1114        13880 :  cvk = ddkop%get_braket(eig0nk, istwf_k, npw_k, nspinor, cwave, mode=my_mode)
    1115         5552 :  vk = cvk(1, :)
    1116              : 
    1117         1388 : end function ddkop_get_vdiag
    1118              : !!***
    1119              : 
    1120              : !!****f* m_ddk/ddkop_get_vnondiag
    1121              : !! NAME
    1122              : !!  ddkop_get_vdiag
    1123              : !!
    1124              : !! FUNCTION
    1125              : !!  Simplified interface to compute the off-diagonal matrix elemente of the velocity operator in cartesian coords.
    1126              : !!
    1127              : !! INPUTS
    1128              : !!
    1129              : !! SOURCE
    1130              : 
    1131            0 : function ddkop_get_vnondiag(ddkop, eig0nk_bra, istwf_k, npw_k, nspinor, cwave_bra, cwave_ket, cwaveprj, mode) result(cvk)
    1132              : 
    1133              : !Arguments ------------------------------------
    1134              : !scalars
    1135              :  class(ddkop_t),intent(inout) :: ddkop
    1136              :  integer,intent(in) :: istwf_k, npw_k, nspinor
    1137              :  real(dp),intent(in) :: eig0nk_bra
    1138              :  character(len=*),optional,intent(in) :: mode
    1139              : !arrays
    1140              :  real(dp),intent(inout) :: cwave_bra(2,npw_k*nspinor),cwave_ket(2,npw_k*nspinor)
    1141              :  type(pawcprj_type),intent(inout) :: cwaveprj(:,:)
    1142              :  real(dp) :: cvk(2,3)
    1143              : 
    1144              : !Local variables-------------------------------
    1145              :  character(len=50) :: my_mode
    1146              : !************************************************************************
    1147              : 
    1148            0 :  my_mode = "cart"; if (present(mode)) my_mode = mode
    1149            0 :  call ddkop%apply(eig0nk_bra, npw_k, nspinor, cwave_ket, cwaveprj)
    1150            0 :  cvk = ddkop%get_braket(eig0nk_bra, istwf_k, npw_k, nspinor, cwave_bra, mode=my_mode)
    1151              : 
    1152            0 : end function ddkop_get_vnondiag
    1153              : !!***
    1154              : 
    1155              : !----------------------------------------------------------------------
    1156              : 
    1157              : !!****f* m_ddk/ddkop_free
    1158              : !! NAME
    1159              : !!  ddkop_free
    1160              : !!
    1161              : !! FUNCTION
    1162              : !!  Free memory
    1163              : !!
    1164              : !! SOURCE
    1165              : 
    1166           74 : subroutine ddkop_free(ddkop)
    1167              : 
    1168              : !Arguments ------------------------------------
    1169              : !scalars
    1170              :  class(ddkop_t),intent(inout) :: ddkop
    1171              : 
    1172              : !Local variables-------------------------------
    1173              :  integer :: idir
    1174              : !************************************************************************
    1175              : 
    1176           74 :  ABI_SFREE(ddkop%gh1c)
    1177           74 :  ABI_SFREE(ddkop%gs1c)
    1178              : 
    1179          296 :  do idir=1,3
    1180          222 :    call ddkop%gs_hamkq(idir)%free()
    1181          222 :    call ddkop%htg(idir)%free()
    1182          296 :    call ddkop%rf_hamkq(idir)%free()
    1183              :  end do
    1184              : 
    1185           74 :  ddkop%mpi_enreg => null()
    1186              : 
    1187           74 : end subroutine ddkop_free
    1188              : !!***
    1189              : 
    1190              : !----------------------------------------------------------------------
    1191              : 
    1192              : !!****f* m_ddk/ham_targets_free
    1193              : !! NAME
    1194              : !!
    1195              : !! FUNCTION
    1196              : !!
    1197              : !! INPUTS
    1198              : !!
    1199              : !! SOURCE
    1200              : 
    1201         1305 : subroutine ham_targets_free(ddkop)
    1202              : 
    1203              : !Arguments ------------------------------------
    1204              :  class(ham_targets_t),intent(inout) :: ddkop
    1205              : !************************************************************************
    1206              : 
    1207         1305 :  ABI_SFREE(ddkop%ffnlk)
    1208         1305 :  ABI_SFREE(ddkop%ffnl1)
    1209         1305 :  ABI_SFREE(ddkop%kpg_k)
    1210         1305 :  ABI_SFREE(ddkop%kpg1_k)
    1211         1305 :  ABI_SFREE(ddkop%dkinpw)
    1212         1305 :  ABI_SFREE(ddkop%kinpw1)
    1213         1305 :  ABI_SFREE(ddkop%ph3d)
    1214         1305 :  ABI_SFREE(ddkop%ph3d1)
    1215              : 
    1216         1305 : end subroutine ham_targets_free
    1217              : !!***
    1218              : 
    1219              : !----------------------------------------------------------------------
    1220              : 
    1221         5476 : end module m_ddk
    1222              : !!***
        

Generated by: LCOV version 2.3-1