LCOV - code coverage report
Current view: top level - src/78_eph - m_eph_path.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.8 % 391 308
Test Date: 2026-11-10 13:31:01 Functions: 100.0 % 1 1
Branches: 45.9 % 1291 593

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_eph_path
       2                 :             : !! NAME
       3                 :             : !!  m_eph_path
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Compute e-ph matrix elements g(k,q) along an arbitrary path either in k- or q-space.
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2008-2026 ABINIT group (MG)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_eph_path
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_abicore
      26                 :             :  use m_xmpi
      27                 :             :  use m_mpinfo
      28                 :             :  use m_errors
      29                 :             :  use m_copy
      30                 :             :  use m_hamiltonian
      31                 :             :  use m_pawcprj
      32                 :             :  use m_ephtk
      33                 :             :  use netcdf
      34                 :             :  use m_nctk
      35                 :             : 
      36                 :             :  use defs_abitypes,    only : mpi_type
      37                 :             :  use defs_datatypes,   only : pseudopotential_type
      38                 :             :  use m_time,           only : cwtime, cwtime_report, timab, sec2str
      39                 :             :  use m_fstrings,       only : itoa, ftoa, sjoin, ktoa, ltoa, strcat
      40                 :             :  use m_cgtools,        only : cg_zdotc
      41                 :             :  use m_crystal,        only : crystal_t
      42                 :             :  use m_dtset,          only : dataset_type
      43                 :             :  use m_dtfil,          only : datafiles_type
      44                 :             :  use m_ebands,         only : ebands_t
      45                 :             :  use m_getgh1c,        only : getgh1c, rf_transgrid_and_pack
      46                 :             :  use m_pawang,         only : pawang_type
      47                 :             :  use m_pawrad,         only : pawrad_type
      48                 :             :  use m_pawtab,         only : pawtab_type
      49                 :             :  use m_pawfgr,         only : pawfgr_type
      50                 :             :  use m_cgwf,           only : nscf_t
      51                 :             :  use m_bz_mesh,        only : kpath_t
      52                 :             :  use m_wfd,            only : u0_cache_t
      53                 :             :  use m_ifc,            only : ifc_type
      54                 :             :  use m_dvdb,           only : dvdb_t
      55                 :             :  use m_mlwfovlp,       only : wan_t
      56                 :             : 
      57                 :             :  implicit none
      58                 :             : 
      59                 :             :  private
      60                 :             : !!***
      61                 :             : 
      62                 :             :  public :: eph_path_run
      63                 :             : 
      64                 :             : contains  !=====================================================
      65                 :             : !!***
      66                 :             : 
      67                 :             : !----------------------------------------------------------------------
      68                 :             : 
      69                 :             : !!****f* m_eph_path/eph_path_run
      70                 :             : !! NAME
      71                 :             : !!  eph_path_run
      72                 :             : !!
      73                 :             : !! FUNCTION
      74                 :             : !!  Compute e-ph matrix elements g(k,q) along an arbitrary path either in k- or q-space.
      75                 :             : !!  Wavefunctions at k and k+q are computed non-self-consistently by invoking the CG eigensolver
      76                 :             : !!  starting from the GS potential read from file.
      77                 :             : !!  The DFPT potentials at q are usually obtained via Fourier interpolation, but it is also possible
      78                 :             : !!  to use fully ab-initio potentials provided the DVDB file contains all the q-points along the path.
      79                 :             : !!  This requires performing DFPT calculations for all the q-points, and then merging
      80                 :             : !!  all the POT1 files with the mrgdv utility.
      81                 :             : !!
      82                 :             : !! INPUTS
      83                 :             : !! dtfil<datafiles_type>=Variables related to files.
      84                 :             : !! dtset<dataset_type>=All input variables for this dataset.
      85                 :             : !! cryst<crystal_t>=crystal structure parameters
      86                 :             : !! wfk_ebands: electron bands from the input WFK file (used to propagate nelect and fermie to GPATH.nc)
      87                 :             : !! dvdb<dbdb_type>=Database with the DFPT SCF potentials.
      88                 :             : !! ifc<ifc_type>=interatomic force constants and corresponding real space grid info.
      89                 :             : !! pawfgr <type(pawfgr_type)>=fine grid parameters and related data
      90                 :             : !! pawang<pawang_type)>=PAW angular mesh and related data.
      91                 :             : !! pawrad(ntypat*usepaw)<pawrad_type>=Paw radial mesh and related data.
      92                 :             : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
      93                 :             : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
      94                 :             : !! comm=MPI communicator.
      95                 :             : !!
      96                 :             : !! OUTPUT
      97                 :             : !! Only writing.
      98                 :             : !!
      99                 :             : !! SOURCE
     100                 :             : 
     101                 :           2 : subroutine eph_path_run(dtfil, dtset, cryst, wfk_ebands, dvdb, ifc, pawfgr, pawang, pawrad, pawtab, psps, comm)
     102                 :             : 
     103                 :             : !Arguments ------------------------------------
     104                 :             : !scalars
     105                 :             :  type(datafiles_type),intent(in) :: dtfil
     106                 :             :  type(dataset_type),intent(in) :: dtset
     107                 :             :  type(crystal_t),intent(in) :: cryst
     108                 :             :  type(ebands_t),intent(in) :: wfk_ebands
     109                 :             :  type(dvdb_t),intent(inout) :: dvdb
     110                 :             :  type(pawang_type),intent(in) :: pawang
     111                 :             :  type(pseudopotential_type),intent(in) :: psps
     112                 :             :  type(pawfgr_type),intent(in) :: pawfgr
     113                 :             :  type(ifc_type),intent(in) :: ifc
     114                 :             :  integer,intent(in) :: comm
     115                 :             : !arrays
     116                 :             :  type(pawrad_type),intent(in) :: pawrad(psps%ntypat*psps%usepaw)
     117                 :             :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
     118                 :             : 
     119                 :             : !Local variables ------------------------------
     120                 :             : !scalars
     121                 :             :  integer,parameter :: istwfk_1 = 1, tim_getgh1c = 1, berryopt0 = 0, master = 0, ndims = 3, ndat1 = 1
     122                 :             :  integer :: sij_opt,usecprj,usevnl,optlocal,optnl,opt_gvnlx1, nu
     123                 :             :  integer :: spin, iq, ik, nk_path, nq_path, ierr, npw_k, npw_kq, my_rank, nprocs, n1, n2, n3, n4, n5, n6, cplex
     124                 :             :  integer :: natom, natom3, nsppol, nspden, nspinor, qptopt, comm_cart, me_cart
     125                 :             :  integer :: nfft,nfftf,mgfft,mgfftf, my_npert, my_ip, idir, ipert, ipc, ncerr, ncid, my_nkpath, my_nqpath
     126                 :             :  integer :: in_k, im_kq, my_is, my_ik, my_iq, nband, nb_in_g, ii, band_n, band_m, bstart, bstop, my_nspins, np, tot_nscf_ierr
     127                 :             :  integer :: my_pert_start_glob, nwan_glob, iglob
     128                 :             :  real(dp) :: cpu_all,wall_all,gflops_all, eig0nk, eshift
     129                 :             :  logical :: qq_is_gamma, need_ftinterp, gen_eigenpb, use_cg_k, use_cg_kq, use_cache, has_gwan
     130                 :           2 :  type(gs_hamiltonian_type) :: gs_ham_k, gs_ham_kq
     131                 :           2 :  type(rf_hamiltonian_type) :: rf_ham_kq
     132                 :           2 :  type(nscf_t) :: nscf
     133                 :           2 :  type(kpath_t) :: qpath, kpath
     134                 :             :  type(xcomm_t),target :: kpt_comm, qpt_comm, pert_comm
     135   [ +  +  +  + ]:          14 :  type(u0_cache_t) :: ucache_kq, ucache_k
     136   [ +  +  +  + ]:          14 :  type(wan_t) :: wan
     137                 :             :  character(len=fnlen) :: gpath_path
     138                 :             :  character(len=5000) :: msg
     139                 :             :  character(len=10) :: priority
     140                 :             : !!arrays
     141                 :             :  integer :: units(2), ngfft(18),ngfftf(18), coords_spin(ndims), dims(ndims)
     142                 :           2 :  integer,allocatable :: kg_k(:,:), kg_kq(:,:), qmap_symrec(:,:), my_ik_inds(:), my_iq_inds(:), my_spins(:), my_iperts(:)
     143                 :           2 :  integer,allocatable :: pert_table(:,:), my_pinfo(:,:)
     144                 :           4 :  real(dp) :: kk(3), qq(3), kq(3), phfreqs(3*cryst%natom), phfreqs_ev(3*cryst%natom), fake_path(3,2)
     145                 :           2 :  real(dp),allocatable :: grad_berry(:,:), kinpw_k(:), kinpw_kq(:)
     146                 :           2 :  real(dp),allocatable :: cg_k(:,:,:), cg_kq(:,:,:), gsc_k(:,:,:), gsc_kq(:,:,:),eig_k(:), eig_kq(:)
     147                 :           2 :  real(dp),allocatable :: eig_k_wan(:), eig_kq_wan(:,:)
     148                 :           4 :  real(dp),allocatable :: v1scf(:,:,:,:), vlocal1(:,:,:,:), vlocal(:,:,:,:), gkq_atm(:,:,:,:), gkq_nu(:,:,:,:), gkq2_nu(:,:,:)
     149                 :           2 :  real(dp),allocatable :: gkq_atm_wan(:,:,:,:), gkq_nu_wan(:,:,:,:), gkq2_nu_wan(:,:,:)
     150                 :           2 :  complex(dp),allocatable :: g_atm_wan_local(:,:,:,:)
     151                 :           2 :  real(dp),allocatable :: gvnlx1(:,:), gs1c(:,:), h1_kets_kq(:,:,:), displ_cart(:,:,:,:),displ_red_qq(:,:,:,:)
     152                 :           4 :  real(dp),allocatable :: kpg_k(:,:), ph3d_k(:,:,:), ffnl_k(:,:,:,:), vlocal_k(:,:,:,:)
     153                 :           2 :  real(dp),allocatable :: kpg_kq(:,:), ph3d_kq(:,:,:), ffnl_kq(:,:,:,:), vlocal_kq(:,:,:,:), real_vec(:)
     154                 :             :  logical :: reorder, periods(ndims), keepdim(ndims)
     155                 :           2 :  type(pawcprj_type),allocatable  :: cwaveprj0(:,:)
     156                 :           2 :  type(xcomm_t),allocatable :: comm_my_is(:)
     157                 :             : !************************************************************************
     158                 :             : 
     159         [ -  + ]:           2 :  if (psps%usepaw == 1) then
     160                 :           0 :    ABI_ERROR("PAW not implemented")
     161                 :             :    ABI_UNUSED((/pawang%nsym, pawrad(1)%mesh_size/))
     162                 :             :  end if
     163                 :             : 
     164                 :           2 :  call cwtime(cpu_all, wall_all, gflops_all, "start")
     165                 :           2 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     166         [ +  + ]:           6 :  units = [std_out, ab_out]
     167                 :             : 
     168                 :             :  ! Copy important dimensions.
     169                 :           2 :  natom = cryst%natom; natom3 = 3 * natom; nsppol = dtset%nsppol; nspinor = dtset%nspinor; nspden = dtset%nspden
     170                 :             : 
     171                 :             :  ! Build (k/q)-path. NB: Input variables have been already checked for consistency in chkinp.
     172                 :           1 :  select case (dtset%eph_fix_korq)
     173                 :             :  case ("k")
     174                 :           1 :    call qpath%init(dtset%ph_qpath(:,1:dtset%ph_nqpath), cryst%gprimd, dtset%ph_ndivsm)
     175                 :           1 :    nq_path = qpath%npts
     176                 :           1 :    call qpath%print(units, header=sjoin("q-point path for g(k,q) with fixed k:", ktoa(dtset%eph_fix_wavevec)), prtvol=dtset%prtvol)
     177   [ +  +  +  + ]:           7 :    fake_path(:,1) = dtset%eph_fix_wavevec; fake_path(:,2) = dtset%eph_fix_wavevec + one
     178                 :           1 :    call kpath%init(fake_path, cryst%gprimd, 0)
     179                 :           1 :    nk_path = 1
     180                 :             : 
     181                 :             :  case ("q")
     182                 :           1 :    call kpath%init(dtset%kptbounds(:,1:dtset%nkpath), cryst%gprimd, dtset%ndivsm)
     183                 :           1 :    nk_path = kpath%npts
     184                 :           1 :    call kpath%print(units, header=sjoin("k-point path for g(k,q) with fixed q:", ktoa(dtset%eph_fix_wavevec)), prtvol=dtset%prtvol)
     185   [ +  +  +  + ]:           7 :    fake_path(:,1) = dtset%eph_fix_wavevec; fake_path(:,2) = dtset%eph_fix_wavevec + one
     186                 :           1 :    call qpath%init(fake_path, cryst%gprimd, 0)
     187                 :           1 :    nq_path = 1
     188                 :             : 
     189                 :             :  case default
     190      [ +  +  - ]:           2 :    ABI_ERROR(sjoin("Invalid value of eph_fix_korq:", dtset%eph_fix_korq))
     191                 :             :  end select
     192                 :             : 
     193                 :             :  ! Define band range and nb_in_g from eph_path_brange.
     194                 :           2 :  nband = dtset%mband; bstart = dtset%eph_path_brange(1); bstop = dtset%eph_path_brange(2)
     195                 :             : 
     196                 :             :  ! Check whether e-ph matrix elements should also be computed via Wannier interpolation from
     197                 :             :  ! GWAN.nc, for comparison against the ab-initio results computed below.
     198                 :           2 :  has_gwan = (dtfil%filgwanin /= ABI_NOFILE)
     199                 :           2 :  nwan_glob = 0
     200         [ -  + ]:           2 :  if (has_gwan) then
     201         [ #  # ]:           0 :    ABI_CHECK(dtfil%filabiwanin /= ABI_NOFILE, "getgwan_filepath requires getabiwan_filepath to be given as well when eph_task=18.")
     202         [ #  # ]:           0 :    ABI_CHECK(dtset%nsppol == 1, "has_gwan with nsppol == 2 is not yet supported in eph_path_run.")
     203                 :             : 
     204                 :             :    ! Cheap, non-collective read of ABIWAN.nc metadata, purely to validate/auto-set eph_path_brange
     205                 :             :    ! (mirrors gstore_init's has_abiwan branch, m_gstore.F90).
     206                 :           0 :    call wan%from_abiwan(dtfil%filabiwanin, 1, dtset%nsppol, .False., "", xmpi_comm_self)
     207         [ #  # ]:           0 :    if (bstart <= 0 .and. bstop <= 0) then
     208                 :           0 :      bstart = wan%bmin; bstop = wan%bmax
     209         [ #  # ]:           0 :      call wrtout(units, sjoin(" has_gwan: auto-setting eph_path_brange to Wannier band window:", ltoa([bstart,bstop])))
     210                 :             :    else
     211         [ #  # ]:           0 :      if (bstart <= 0) bstart = 1
     212         [ #  # ]:           0 :      if (bstop <= 0) bstop = nband
     213                 :             :      msg = sjoin("eph_path_brange:", ltoa([bstart,bstop]), "must equal [wan%bmin, wan%bmax]:", ltoa([wan%bmin, wan%bmax]), &
     214   [ #  #  #  #  :           0 :                   "when getgwan_filepath is given (the gauge-invariant trace comparison needs the same electronic subspace).")
                   #  # ]
     215   [ #  #  #  # ]:           0 :      ABI_CHECK(bstart == wan%bmin .and. bstop == wan%bmax, msg)
     216                 :             :    end if
     217                 :           0 :    nwan_glob = wan%nwan
     218                 :           0 :    call wan%free()
     219                 :             :  else
     220         [ -  + ]:           2 :    if (bstart <= 0) bstart = 1
     221         [ -  + ]:           2 :    if (bstop <= 0) bstop = nband
     222                 :             :  end if
     223                 :             : 
     224                 :           2 :  nb_in_g = bstop - bstart + 1
     225                 :             : 
     226                 :             :  ! The values of eph_path_brange must be validated at this level!
     227         [ -  + ]:           2 :  ABI_CHECK_IRANGE(bstart, 1, nband, "Wrong eph_path_brange(1)")
     228   [ +  -  -  + ]:           2 :  ABI_CHECK_IRANGE(bstop, 1, nband, "Wrong eph_path_brange(2)")
     229         [ -  + ]:           2 :  ABI_CHECK_IGEQ(bstop, bstart, "eph_path_brange(2) < eph_path_brange(1)")
     230         [ +  + ]:           6 :  call wrtout(units, sjoin(" Computing g(k,q) with eph_path_brange:", ltoa([bstart, bstop])))
     231                 :             : 
     232                 :             :  ! Distribute spins inside input comm.
     233   [ -  +  -  + ]:           2 :  call xmpi_split_nsppol(comm, nsppol, my_nspins, my_spins, comm_my_is)
     234                 :             : 
     235                 :             :  ! ==================
     236                 :             :  ! MPI cartesian grid
     237                 :             :  ! ==================
     238                 :           2 :  my_npert = natom3
     239         [ +  + ]:           4 :  do my_is=1,my_nspins
     240                 :           2 :    spin = my_spins(my_is)
     241                 :           2 :    np = comm_my_is(my_is)%nproc; priority = "12"
     242                 :             : 
     243   [ +  +  +  -  :          12 :    if (any(dtset%eph_np_pqbks /= 0)) then
                   -  + ]
     244                 :             :      ! Take MPI grid from input.
     245                 :           0 :      pert_comm%nproc = dtset%eph_np_pqbks(1)
     246                 :           0 :      qpt_comm%nproc  = dtset%eph_np_pqbks(2)
     247         [ #  # ]:           0 :      ABI_CHECK_IEQ(dtset%eph_np_pqbks(3), 1, "Band parallelism not implemented in eph_path")
     248                 :           0 :      kpt_comm%nproc = dtset%eph_np_pqbks(4)
     249                 :             : 
     250                 :             :    else
     251                 :             :      ! Automatic MPI grid generation.
     252         [ +  + ]:           2 :      if (nk_path == 1) then
     253                 :           1 :        call xmpi_distrib_2d(np, priority, nq_path, natom3, qpt_comm%nproc, pert_comm%nproc, ierr)
     254                 :             :      else
     255                 :           1 :        call xmpi_distrib_2d(np, priority, nk_path, natom3, kpt_comm%nproc, pert_comm%nproc, ierr)
     256                 :             :      end if
     257         [ -  + ]:           2 :      ABI_CHECK(ierr == 0, sjoin("Cannot distribute nprocs:", itoa(np), " with priority: ", priority, ". Decrease MPI nprocs"))
     258                 :             :    end if
     259                 :             : 
     260                 :             :    ! Consistency check
     261                 :           2 :    write(msg, "(a,i2,a,3(i0,1x))")"P Cartesian grid for spin", spin, ": (pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc) = ", &
     262                 :           4 :                                   pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc
     263                 :           2 :    call wrtout(units, msg)
     264                 :             : 
     265         [ -  + ]:           2 :    if (pert_comm%nproc * qpt_comm%nproc * kpt_comm%nproc /= np) then
     266                 :             :      write(msg, "(a,i0,3a, 4(a,1x,i0))") &
     267                 :           0 :        "Cannot create Cartesian grid with nproc(spin): ", np, ch10, &
     268                 :           0 :        "Idle processes are not supported. The product of the `nproc_*` vars should be equal to nproc.", ch10, &
     269                 :           0 :        "qpt_nproc (", qpt_comm%nproc, ") x kpt_nproc (", kpt_comm%nproc, ") x pert_nproc", pert_comm%nproc, &
     270                 :           0 :        ") != ", np
     271                 :           0 :      ABI_ERROR(msg)
     272                 :             :    end if
     273                 :             : 
     274                 :             :    ! For each spin treated by this rank, create MPI cartesian communicator of rank ndims.
     275                 :           2 :    periods(:) = .False.; reorder = .False.
     276         [ +  + ]:           8 :    dims = [pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc]
     277                 :             : 
     278                 :             : #ifdef HAVE_MPI
     279                 :           2 :    call MPI_CART_CREATE(comm_my_is(my_is)%value, ndims, dims, periods, reorder, comm_cart, ierr)
     280                 :             :    ! Find the index and coordinates of the current processor
     281                 :           2 :    call MPI_COMM_RANK(comm_cart, me_cart, ierr)
     282                 :           2 :    call MPI_CART_COORDS(comm_cart, me_cart, ndims, coords_spin, ierr)
     283                 :             : 
     284                 :             :    ! Communicator for q-points in g(k,q)
     285                 :           2 :    keepdim = .False.; keepdim(1) = .True.; call pert_comm%from_cart_sub(comm_cart, keepdim)
     286                 :           2 :    keepdim = .False.; keepdim(2) = .True.; call qpt_comm%from_cart_sub(comm_cart, keepdim)
     287                 :           2 :    keepdim = .False.; keepdim(3) = .True.; call kpt_comm%from_cart_sub(comm_cart, keepdim)
     288                 :           4 :    call xmpi_comm_free(comm_cart)
     289                 :             : #endif
     290                 :             :  end do ! my_is
     291                 :             : 
     292                 :             :  ! Distribute k-points (q-points) inside kpt_comm (qpt_comm) using block distribution.
     293         [ -  + ]:           2 :  call xmpi_split_block(nk_path, kpt_comm%value, my_nkpath, my_ik_inds)
     294         [ -  + ]:           2 :  call xmpi_split_block(nq_path, qpt_comm%value, my_nqpath, my_iq_inds)
     295         [ -  + ]:           2 :  call xmpi_split_block(natom3, pert_comm%value, my_npert, my_iperts)
     296                 :           2 :  my_pert_start_glob = my_iperts(1)
     297                 :           2 :  ABI_FREE(my_iperts)
     298                 :             : 
     299                 :             :  ! Idle processors are not supported (tested).
     300         [ -  + ]:           2 :  ABI_CHECK_IGEQ(my_nkpath, 1, "Too many procs for k-point parallelism.")
     301         [ -  + ]:           2 :  ABI_CHECK_IGEQ(my_nqpath, 1, "Too many procs for q-point parallelism.")
     302         [ -  + ]:           2 :  ABI_CHECK_IGEQ(my_npert, 1, "Too many procs for perturbation parallelism.")
     303                 :             : 
     304         [ -  + ]:           2 :  if (pert_comm%nproc > 1) then
     305                 :             :    ! Build table with list of perturbations treated by this CPU inside pert_comm
     306   [ #  #  #  # ]:           0 :    call ephtk_set_pertables(cryst%natom, my_npert, pert_table, my_pinfo, pert_comm%value)
     307                 :             :    ! Activate parallelism over perturbations
     308                 :           0 :    call dvdb%set_pert_distrib(my_npert, natom3, my_pinfo, pert_table, pert_comm%value)
     309         [ #  # ]:           0 :    ABI_FREE(my_pinfo)
     310         [ #  # ]:           0 :    ABI_FREE(pert_table)
     311                 :           0 :    ABI_WARNING("Parallelism over perturbations should be tested!")
     312                 :             :  end if
     313                 :             : 
     314                 :             :  ! Load KS potential from file.
     315                 :           2 :  call nscf%init(dtset, dtfil, cryst, comm)
     316                 :             : 
     317                 :             :  ! FFT meshes (taken from the GS POT file)
     318   [ +  +  +  + ]:          74 :  ngfft = nscf%ngfft; ngfftf = nscf%ngfftf
     319         [ +  + ]:           8 :  nfftf = product(ngfftf(1:3)); mgfftf = maxval(ngfftf(1:3))
     320         [ +  + ]:           8 :  nfft = product(ngfft(1:3)) ; mgfft = maxval(ngfft(1:3))
     321                 :           2 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); n4 = ngfft(4); n5 = ngfft(5); n6 = ngfft(6)
     322                 :             : 
     323                 :             :  ! Open the DVDB file and make sure we have POT1 files.
     324                 :           2 :  call dvdb%open_read(ngfftf, xmpi_comm_self)
     325         [ -  + ]:           2 :  ABI_CHECK(dvdb%has_fields("pot1", msg), msg)
     326                 :             : 
     327                 :             :  ! Check if all the q-points are present in the DVDB.
     328         [ -  + ]:           2 :  qptopt = dtset%kptopt; if (dtset%qptopt /= 0) qptopt = dtset%qptopt
     329         [ -  + ]:           2 :  call dvdb%need_ftinterp(nq_path, qpath%points, qptopt, qmap_symrec, need_ftinterp)
     330                 :             : 
     331   [ -  +  -  - ]:           2 :  if (.not. need_ftinterp .and. dtset%eph_use_ftinterp /= 0) then
     332                 :           0 :    ABI_COMMENT("Enforcing FT interpolation for q-points even if it's not strictly needed.")
     333                 :           0 :    need_ftinterp = .True.
     334                 :             :  end if
     335                 :             : 
     336         [ +  - ]:           2 :  if (need_ftinterp) then
     337                 :           2 :    call wrtout(units, " Cannot find all q-points in the DVDB --> Activating Fourier interpolation.")
     338                 :           2 :    call dvdb%ftinterp_setup(dtset%ddb_ngqpt, qptopt, 1, dtset%ddb_shiftq, nfftf, ngfftf, xmpi_comm_self)
     339                 :             :  else
     340                 :           0 :    call wrtout(units, " DVDB file contains all q-points along the path --> Reading DFPT potentials from file.")
     341                 :             :  end if
     342                 :             : 
     343                 :             :  ! Prepare call to getgh1c
     344                 :           2 :  usevnl = 0
     345                 :           2 :  optlocal = 1    ! local part of H^(1) is computed in gh1c=<G|H^(1)|C>
     346                 :           2 :  optnl = 2       ! non-local part of H^(1) is totally computed in gh1c=<G|H^(1)|C>
     347                 :           2 :  opt_gvnlx1 = 0  ! gvnlx1 is output
     348                 :           2 :  usecprj = 0
     349                 :             : 
     350         [ -  + ]:           2 :  ABI_MALLOC(gvnlx1, (2, usevnl))
     351   [ -  +  -  + ]:           2 :  ABI_MALLOC(grad_berry, (2, nspinor*(berryopt0/4)))
     352   [ -  +  +  -  :           4 :  ABI_MALLOC(cwaveprj0, (natom, nspinor*usecprj))
          -  +  -  +  -  
                      + ]
     353   [ -  +  +  -  :           8 :  ABI_MALLOC(displ_cart, (2, 3, cryst%natom, natom3))
          -  +  +  -  +  
          -  +  -  -  +  
             -  +  -  + ]
     354   [ -  +  +  -  :           6 :  ABI_MALLOC(displ_red_qq, (2, 3, cryst%natom, natom3))
          -  +  +  -  -  
                +  -  + ]
     355   [ -  +  +  -  :          10 :  ABI_MALLOC(gkq_atm, (2, nb_in_g, nb_in_g, natom3))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                +  -  + ]
     356   [ -  +  +  -  :           8 :  ABI_MALLOC(gkq_nu, (2, nb_in_g, nb_in_g, natom3))
          -  +  +  -  -  
          +  +  -  -  +  
                   -  + ]
     357   [ -  +  +  -  :          10 :  ABI_MALLOC(gkq2_nu, (nb_in_g, nb_in_g, natom3))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                +  -  + ]
     358                 :             : 
     359         [ -  + ]:           2 :  if (has_gwan) then
     360   [ #  #  #  #  :           0 :    ABI_MALLOC(gkq_atm_wan, (2, nwan_glob, nwan_glob, natom3))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     361   [ #  #  #  #  :           0 :    ABI_MALLOC(gkq_nu_wan, (2, nwan_glob, nwan_glob, natom3))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     362   [ #  #  #  #  :           0 :    ABI_MALLOC(gkq2_nu_wan, (nwan_glob, nwan_glob, natom3))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     363   [ #  #  #  #  :           0 :    ABI_MALLOC(eig_k_wan, (nwan_glob))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     364   [ #  #  #  #  :           0 :    ABI_MALLOC(eig_kq_wan, (nwan_glob, 1))
             #  #  #  # ]
     365                 :             :  end if
     366                 :             : 
     367                 :             :  ! Master writes metadata to GPATH file.
     368         [ +  - ]:           2 :  gpath_path = strcat(dtfil%filnam_ds(4), "_GPATH.nc")
     369                 :             : 
     370         [ +  - ]:           2 :  if (my_rank == master) then
     371         [ -  + ]:           2 :    NCF_CHECK(nctk_open_create(ncid, gpath_path, xmpi_comm_self))
     372                 :             :    ! Add crystalline structure.
     373         [ -  + ]:           2 :    NCF_CHECK(cryst%ncwrite(ncid))
     374                 :             : 
     375                 :             :    ! Write dimensions.
     376                 :             :    ncerr = nctk_def_dims(ncid, [ &
     377                 :             :       nctkdim_t("nspinor", nspinor), nctkdim_t("nspden", nspden), nctkdim_t("nsppol", nsppol), &
     378                 :             :       nctkdim_t("nband", nband), nctkdim_t("nb_in_g", nb_in_g), &
     379                 :             :       nctkdim_t("nq_path", nq_path), nctkdim_t("nk_path", nk_path), &
     380                 :             :       nctkdim_t("natom", cryst%natom), nctkdim_t("natom3", natom3), nctkdim_t("number_of_phonon_modes", natom3) &
     381         [ +  + ]:          22 :    ], defmode=.True.)
     382         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     383                 :             : 
     384                 :             :    ! integer scalars
     385                 :             :    ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
     386                 :             :      "bstart", "bstop", "dvdb_add_lr", "used_ftinterp" &
     387         [ +  + ]:          10 :    ])
     388         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     389                 :             : 
     390                 :             :    ! double precision scalars
     391                 :             :    ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
     392                 :             :      "nelect", "fermie"  &
     393         [ +  + ]:           6 :    ])
     394         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     395                 :             : 
     396                 :             :    ncerr = nctk_def_arrays(ncid, [ &
     397                 :             :      nctkarr_t("kpoints", "dp", "three, nk_path"), &
     398                 :             :      nctkarr_t("qpoints", "dp", "three, nq_path"), &
     399                 :             :      nctkarr_t("qweights", "dp", "nq_path"), &
     400                 :             :      nctkarr_t("all_eigens_k", "dp", "nband, nk_path, nsppol"), &
     401                 :             :      nctkarr_t("all_eigens_kq", "dp", "nband, nq_path, nsppol"), &
     402                 :             :      nctkarr_t("gkq2_nu", "dp", "nb_in_g, nb_in_g, natom3, nq_path, nk_path, nsppol"), &
     403                 :             :      nctkarr_t("phfreqs", "dp", "natom3, nq_path"), &
     404                 :             :      nctkarr_t("phdispl_cart", "dp", "two, three, natom, natom3, nq_path"), &
     405                 :             :      nctkarr_t("eph_fix_korq", "c", "one"), &
     406                 :             :      nctkarr_t("eph_fix_wavevec", "dp", "three") &
     407         [ +  + ]:          22 :    ])
     408         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     409                 :             : 
     410         [ -  + ]:           2 :    NCF_CHECK(nf90_def_var_fill(ncid, vid("gkq2_nu"), NF90_FILL, -one))
     411         [ -  + ]:           2 :    NCF_CHECK(nf90_def_var_fill(ncid, vid("phfreqs"), NF90_FILL, -one))
     412                 :             : 
     413         [ -  + ]:           2 :    if (has_gwan) then
     414         [ #  # ]:           0 :      ncerr = nctk_def_dims(ncid, [nctkdim_t("nwan", nwan_glob)], defmode=.True.)
     415         [ #  # ]:           0 :      NCF_CHECK(ncerr)
     416                 :             :      ncerr = nctk_def_arrays(ncid, [ &
     417                 :             :        ! Use the same path convention as the ab-initio eigenvalues: k varies when q
     418                 :             :        ! is fixed, whereas k+q varies with q when k is fixed.
     419                 :             :        nctkarr_t("all_eigens_wan_k", "dp", "nwan, nk_path, nsppol"), &
     420                 :             :        nctkarr_t("all_eigens_wan_kq", "dp", "nwan, nq_path, nsppol"), &
     421                 :             :        nctkarr_t("gkq2_nu_wan", "dp", "nwan, nwan, natom3, nq_path, nk_path, nsppol") &
     422         [ #  # ]:           0 :      ])
     423         [ #  # ]:           0 :      NCF_CHECK(ncerr)
     424         [ #  # ]:           0 :      NCF_CHECK(nf90_def_var_fill(ncid, vid("gkq2_nu_wan"), NF90_FILL, -one))
     425                 :             :    end if
     426                 :             : 
     427                 :             :    ! Write data.
     428         [ -  + ]:           2 :    NCF_CHECK(nctk_set_datamode(ncid))
     429         [ -  + ]:           2 :    ii = merge(1, 0, need_ftinterp)
     430                 :             :    ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
     431                 :             :      "bstart", "bstop", "dvdb_add_lr", "used_ftinterp"], &
     432                 :             :      [bstart, bstop, dtset%dvdb_add_lr, ii  &
     433   [ +  +  +  + ]:          18 :    ])
     434         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     435                 :             : 
     436                 :             :    ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
     437                 :             :      "nelect", "fermie"], &
     438                 :             :      [wfk_ebands%nelect, wfk_ebands%fermie &
     439   [ +  +  +  + ]:          10 :    ])
     440         [ -  + ]:           2 :    NCF_CHECK(ncerr)
     441                 :             : 
     442                 :             :    ! arrays
     443         [ -  + ]:           2 :    NCF_CHECK(nf90_put_var(ncid, vid("kpoints"), kpath%points(:,1:nk_path)))
     444         [ -  + ]:           2 :    NCF_CHECK(nf90_put_var(ncid, vid("qpoints"), qpath%points(:,1:nq_path)))
     445   [ -  +  +  -  :           6 :    ABI_MALLOC(real_vec, (nq_path))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     446         [ +  + ]:          45 :    real_vec = one
     447         [ -  + ]:           2 :    NCF_CHECK(nf90_put_var(ncid, vid("qweights"), real_vec))
     448         [ -  + ]:           2 :    ABI_FREE(real_vec)
     449         [ -  + ]:           2 :    NCF_CHECK(nf90_put_var(ncid, vid("eph_fix_korq"), dtset%eph_fix_korq))
     450         [ -  + ]:           2 :    NCF_CHECK(nf90_put_var(ncid, vid("eph_fix_wavevec"), dtset%eph_fix_wavevec))
     451                 :             : 
     452                 :             :    ! Compute non-analytic phonons for q--> 0 in polar materials.
     453   [ +  -  +  -  :           2 :    if (nq_path > 1 .and. (any(ifc%zeff /= zero))) call ifc%calcnwrite_nana_terms_qpath(qpath, cryst, ncid, units)
          +  -  -  +  +  
                +  +  - ]
     454         [ -  + ]:           2 :    NCF_CHECK(nf90_close(ncid))
     455                 :             :  end if ! master
     456                 :             : 
     457                 :             :  ! Make sure the netcdf file has been written by master before continuing.
     458                 :           2 :  call xmpi_barrier(comm)
     459                 :             : 
     460                 :             :  ! All procs open the GPATH file here.
     461                 :             :  ! FIXME
     462                 :             :  !NCF_CHECK(nctk_open_modify(ncid, gpath_path, comm))
     463         [ -  + ]:           2 :  NCF_CHECK(nctk_open_modify(ncid, gpath_path, xmpi_comm_self))
     464                 :             : 
     465                 :             :  ! The cache allows one the reuse the wavefunctions of the previous k/q to init the NSCF cycle
     466                 :             :  ! It usually reduces the number of iterations by 3-4 but it requires more memory.
     467                 :           2 :  tot_nscf_ierr = 0; use_cache = .True. !; use_cache = .False.
     468         [ +  + ]:           3 :  call ucache_k%init(use_cache .and. my_nkpath > 1, ngfft)
     469         [ +  + ]:           3 :  call ucache_kq%init(use_cache .and. my_nqpath > 1, ngfft)
     470                 :             : 
     471                 :             :  ! Loop over spins (MPI parallelized)
     472         [ +  + ]:           4 :  do my_is=1,my_nspins
     473                 :           2 :    spin = my_spins(my_is)
     474                 :             : 
     475         [ -  + ]:           2 :    if (has_gwan) then
     476                 :             :      ! Build wan for this spin from the ABIWAN.nc file, set the perturbation distribution
     477                 :             :      ! from THIS routine's own pert_comm (same natom3 block-distribution used for the
     478                 :             :      ! ab-initio gkq_atm below), then load g(R_e, R_p) from GWAN.nc.
     479                 :           0 :      call wan%from_abiwan(dtfil%filabiwanin, spin, dtset%nsppol, .False., "", comm_my_is(my_is)%value)
     480                 :           0 :      wan%my_pert_start = my_pert_start_glob; wan%my_npert = my_npert; wan%pert_comm => pert_comm
     481                 :           0 :      call wan%load_gwan(dtfil%filgwanin, cryst, spin, dtset%nsppol, comm_my_is(my_is))
     482                 :             :    end if
     483                 :             : 
     484                 :             :    ! Loop over k-points in k-path (MPI parallelized).
     485         [ +  + ]:          45 :    do my_ik=1,my_nkpath
     486         [ +  + ]:         172 :      ik = my_ik_inds(my_ik); kk = kpath%points(:, ik)
     487                 :             :      !print *, "ik, kk", ik, kk
     488                 :             : 
     489                 :             :      ! Prepare NSCF run at k.
     490                 :             :      ! gs_ham_k has pointers to the *_k arrays in output so we cannot deallocate them till the end.
     491                 :             :      ! This is the reason why we use vlocal_k although this term does not depend on k
     492                 :             :      call nscf%setup_kpt(spin, kk, istwfk_1, nband, cryst, dtset, psps, pawtab, pawfgr, &              ! in
     493   [ -  +  -  +  :          43 :                          npw_k, kg_k, kpg_k, ph3d_k, kinpw_k, ffnl_k, vlocal_k, cg_k, gsc_k, gs_ham_k) ! out
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     494                 :             : 
     495                 :             :      ! Cache to initialize u_{nk}(g).
     496   [ +  +  -  + ]:          43 :      use_cg_k = (my_ik > 1 .and. ucache_k%use_cache)
     497         [ +  + ]:          43 :      if (use_cg_k) call ucache_k%get_kpt(kk, istwfk_1, npw_k, nspinor, nband, kg_k, cg_k)
     498                 :             : 
     499                 :             :      ! Compute u_{nk}(g)
     500                 :             :      call nscf%solve_kpt(spin, kk, istwfk_1, nband, cryst, dtset, dtfil, gs_ham_k, &
     501         [ -  + ]:          43 :                          use_cg_k, npw_k, cg_k, gsc_k, eig_k, msg, ierr)
     502                 :             : 
     503         [ -  + ]:          43 :      ABI_WARNING_IF(ierr /= 0, msg)
     504                 :          43 :      tot_nscf_ierr = tot_nscf_ierr + ierr
     505                 :             : 
     506                 :          43 :      call ucache_k%store_kpt(kk, istwfk_1, npw_k, nspinor, nband, kg_k, cg_k)
     507                 :             : 
     508                 :             :      !if (pert_comm%me == master) then
     509   [ +  +  -  +  :         172 :      NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_k"), eig_k, start=[1,ik,spin]))
                   -  - ]
     510                 :             :      !end if
     511                 :             : 
     512                 :             :      ! Make sure all procs in pert_comm have the same wavefunctions at k.
     513                 :          43 :      call xmpi_bcast(cg_k, master, pert_comm%value, ierr)
     514         [ -  + ]:          43 :      if (psps%usepaw == 1) call xmpi_bcast(gsc_k, master, pert_comm%value, ierr)
     515                 :             : 
     516                 :             :      ! Allocate vlocal. Note nvloc
     517   [ -  +  +  -  :         258 :      ABI_MALLOC(vlocal, (n4, n5, n6, gs_ham_k%nvloc))
          -  +  +  -  -  
          +  +  -  -  +  
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     518                 :             : 
     519                 :             :      ! Loop over q-points in q-path (MPI parallelized).
     520                 :             :      ! All procs in pert_comm enter this loop with the same ik/iq indices.
     521         [ +  + ]:         127 :      do my_iq=1,my_nqpath
     522   [ +  +  +  + ]:         588 :        iq = my_iq_inds(my_iq); qq = qpath%points(:,iq); qq_is_gamma = sum(qq**2) < tol14
     523         [ +  + ]:         336 :        kq = kk + qq
     524                 :             :        !print *, "iq, kq", iq, kq
     525                 :             : 
     526                 :             :        ! Prepare NSCF run at k+q.
     527                 :             :        ! gs_ham_kq has pointers to the *_kq arrays in output so we cannot deallocate them till the end.
     528                 :             :        ! This is the reason why we use vlocal_kq although this term does not depend on k+q.
     529                 :             :        call nscf%setup_kpt(spin, kq, istwfk_1, nband, cryst, dtset, psps, pawtab, pawfgr, &                         ! in
     530   [ -  +  -  +  :          84 :                            npw_kq, kg_kq, kpg_kq, ph3d_kq, kinpw_kq, ffnl_kq, vlocal_kq, cg_kq, gsc_kq, gs_ham_kq)  ! out
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
     531                 :             : 
     532                 :             :        ! Cache for u_{m k+q}(g).
     533   [ +  +  -  + ]:          84 :        use_cg_kq = (my_iq > 1 .and. ucache_kq%use_cache)
     534         [ +  + ]:          84 :        if (use_cg_kq) call ucache_kq%get_kpt(kq, istwfk_1, npw_kq, nspinor, nband, kg_kq, cg_kq)
     535                 :             : 
     536                 :             :        ! We can use cg_k as input for the NSCF for a very quick return.
     537         [ +  + ]:          84 :        if (qq_is_gamma) then
     538   [ +  -  +  -  :      134284 :          use_cg_kq = .True.; cg_kq = cg_k
          +  -  -  +  -  
          -  -  -  -  -  
          -  -  +  +  +  
                +  +  + ]
     539                 :             :        end if
     540                 :             : 
     541                 :             :        ! Compute u_{m k+q}(g)
     542                 :             :        call nscf%solve_kpt(spin, kq, istwfk_1, nband, cryst, dtset, dtfil, gs_ham_kq, &
     543         [ -  + ]:          84 :                            use_cg_kq, npw_kq, cg_kq, gsc_kq, eig_kq, msg, ierr)
     544                 :             : 
     545         [ -  + ]:          84 :        ABI_WARNING_IF(ierr /= 0, msg)
     546                 :          84 :        tot_nscf_ierr = tot_nscf_ierr + ierr
     547                 :             : 
     548                 :          84 :        call ucache_kq%store_kpt(kq, istwfk_1, npw_kq, nspinor, nband, kg_kq, cg_kq)
     549                 :             : 
     550                 :             :        ! This to have the same gauge when qq = 0.
     551   [ +  +  +  -  :      134366 :        if (qq_is_gamma) cg_kq = cg_k
          +  -  +  -  -  
          +  -  -  -  -  
          -  -  -  -  +  
             +  +  +  +  
                      + ]
     552                 :             : 
     553                 :             :        ! Make sure all procs in pert_comm have the same wavefunctions at k+q.
     554                 :          84 :        call xmpi_bcast(cg_kq, master, pert_comm%value, ierr)
     555         [ -  + ]:          84 :        if (psps%usepaw == 1) call xmpi_bcast(gsc_kq, master, pert_comm%value, ierr)
     556                 :             : 
     557                 :             :        ! Get phonons for this q-point.
     558                 :          84 :        call ifc%fourq(cryst, qq, phfreqs, displ_cart, out_displ_red=displ_red_qq)
     559         [ +  + ]:         588 :        phfreqs_eV = phfreqs * Ha_eV
     560                 :             : 
     561                 :             :        ! Only the global first k-point contributes to q-path-only variables.
     562         [ +  + ]:          84 :        if (ik == 1) then
     563   [ +  +  -  +  :         172 :          NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_kq"), eig_kq, start=[1,iq,spin]))
                   -  - ]
     564                 :             :          ! Write phonons for this qpt.
     565         [ +  - ]:          43 :          if (spin == 1) then
     566   [ +  +  -  +  :         129 :            NCF_CHECK(nf90_put_var(ncid, vid("phfreqs"), phfreqs_ev, start=[1,iq]))
                   -  - ]
     567   [ +  +  -  +  :         258 :            NCF_CHECK(nf90_put_var(ncid, vid("phdispl_cart"), displ_cart, start=[1,1,1,1,iq]))
                   -  - ]
     568                 :             :          end if
     569                 :             :        end if
     570                 :             : 
     571                 :             :        ! For PAW, one has to solve a generalized eigenproblem.
     572         [ -  + ]:          84 :        gen_eigenpb = psps%usepaw == 1; sij_opt = 0; if (gen_eigenpb) sij_opt = 1
     573   [ +  -  -  -  :         252 :        ABI_MALLOC(gs1c, (2, npw_kq*nspinor*((sij_opt+1)/2)))
          +  -  -  +  -  
                +  -  + ]
     574   [ -  +  +  -  :         336 :        ABI_MALLOC(h1_kets_kq, (2, npw_kq*nspinor, nb_in_g))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     575                 :             : 
     576                 :             :        ! ====================================
     577                 :             :        ! Get DFPT potentials for this q-point
     578                 :             :        ! ====================================
     579                 :             :        ! After this branch we have allocated v1scf(cplex, nfftf, nspden, my_npert)).
     580         [ +  - ]:          84 :        if (need_ftinterp) then
     581         [ -  + ]:          84 :          call dvdb%get_ftqbz(qq, cplex, nfftf, ngfftf, v1scf, pert_comm%value)
     582                 :             :        else
     583                 :             :          ! Read and reconstruct the dvscf potentials for qq and my_npert perturbations.
     584         [ #  # ]:           0 :          call dvdb%readsym_qbz(cryst, qq, qmap_symrec(:,iq), cplex, nfftf, ngfftf, v1scf, pert_comm%value)
     585                 :             :        end if
     586                 :             : 
     587                 :             :        ! Allocate vlocal1 with correct cplex. Note nvloc.
     588   [ -  +  +  -  :         504 :        ABI_MALLOC(vlocal1, (cplex*n4, n5, n6, gs_ham_kq%nvloc))
          -  +  +  -  -  
          +  +  -  -  +  
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     589                 :             : 
     590                 :             :        ! Load the k/k+q dependent parts of the Hamiltonian.
     591                 :             :        ! NB: In this routine we have to use gs_ham_k to have {k+q}_H0_k.
     592                 :             :        ! Using gs_ham_kq would be wrong as it would lead to {k+q}_H0_{k+q}.
     593                 :             : 
     594                 :             :        call gs_ham_k%load_kprime(kpt_kp=kq, npw_kp=npw_kq, istwf_kp=istwfk_1, kg_kp=kg_kq, kpg_kp=kpg_kq, kinpw_kp=kinpw_kq, &
     595                 :          84 :                                  ph3d_kp=ph3d_kq, ffnl_kp=ffnl_kq, compute_ph3d=.true., compute_gbound=.true.)
     596                 :             :        !call gs_ham_k%print([std_out], "gs_ham_k after load", dtset%prtvol)
     597                 :             : 
     598                 :             :        ! Loop over my atomic perturbations: apply H1_{kappa, alpha} and compute gkq_atm.
     599   [ +  +  +  +  :       15708 :        gkq_atm = zero
             +  +  +  + ]
     600         [ +  + ]:         588 :        do my_ip=1,my_npert
     601                 :         504 :          idir = dvdb%my_pinfo(1, my_ip); ipert = dvdb%my_pinfo(2, my_ip); ipc = dvdb%my_pinfo(3, my_ip)
     602                 :             : 
     603                 :             :          ! Set up local potential vlocal1 with proper dimensioning from vtrial1 taking into account the spin.
     604                 :             :          call rf_transgrid_and_pack(spin, nspden, psps%usepaw, cplex, nfftf, nfft, ngfft, gs_ham_kq%nvloc,&
     605                 :         504 :                                     pawfgr, nscf%mpi_enreg, nscf%vtrial, v1scf(:,:,:,my_ip), vlocal, vlocal1)
     606                 :             : 
     607                 :             :          ! Prepare application of the NL part.
     608                 :         504 :          call rf_ham_kq%init(cplex, gs_ham_k, ipert, has_e1kbsc=.true.)
     609                 :         504 :          call rf_ham_kq%load_spin(spin, vlocal1=vlocal1, with_nonlocal=.true.)
     610                 :             :          ! Load k-dependent part in the 1st-order Hamiltonian datastructure
     611                 :             :          !call rf_ham_kq%load_k(npw_k=npw_k)
     612                 :             : 
     613                 :             :          ! Calculate dvscf * psi_k, results stored in h1_kets_kq on the k+q sphere.
     614                 :             :          ! Compute H(1) applied to GS wavefunction Psi(0).
     615         [ +  + ]:        2016 :          do in_k=1,nb_in_g
     616                 :        1512 :            band_n = in_k + bstart - 1
     617                 :        1512 :            eig0nk = eig_k(band_n)
     618                 :             :            ! Use scissor shift on 0-order eigenvalue.
     619                 :        1512 :            eshift = eig0nk - dtset%dfpt_sciss
     620                 :             : 
     621                 :             :            call getgh1c(berryopt0, cg_k(:,:,band_n), cwaveprj0, h1_kets_kq(:,:,in_k), &
     622                 :             :                         grad_berry, gs1c, gs_ham_k, gvnlx1, idir, ipert, [eshift], nscf%mpi_enreg, ndat1, optlocal, &
     623         [ +  + ]:        3528 :                         optnl, opt_gvnlx1, rf_ham_kq, sij_opt, tim_getgh1c, usevnl)
     624                 :             :            !print *, "maxval(abs(h1_kets_kq(:,:,in_k))): ", maxval(abs(h1_kets_kq(:,:,in_k)))
     625                 :             :          end do ! in_k
     626                 :             : 
     627                 :             :          ! Calculate <psi_{k+q,j}|dvscf_q*psi_{k,i}> for this perturbation. No need to handle istwf_kq because it's always 1.
     628                 :             :          !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(band_m)
     629         [ +  + ]:        2100 :          do in_k=1,nb_in_g
     630         [ +  + ]:        6552 :            do im_kq=1,nb_in_g
     631                 :        4536 :              band_m = im_kq + bstart - 1
     632                 :        6048 :              gkq_atm(:, im_kq, in_k, ipc) = cg_zdotc(npw_kq*nspinor, cg_kq(:,:,band_m), h1_kets_kq(:,:,in_k))
     633                 :             :            end do
     634                 :             :          end do
     635                 :             : 
     636                 :             :        end do ! my_ip
     637                 :             : 
     638                 :             :        ! Collect gkq_atm inside pert_comm so that all procs can operate on the data.
     639         [ -  + ]:          84 :        if (pert_comm%nproc > 1) call xmpi_sum(gkq_atm, pert_comm%value, ierr)
     640                 :             : 
     641                 :             :        ! From atom to phonon mode representation. Results stored in gkq_nu.
     642                 :          84 :        call ephtk_gkknu_from_atm(nb_in_g, nb_in_g, 1, natom, gkq_atm, phfreqs, displ_red_qq, gkq_nu)
     643                 :             :        !print *, "gkq_atm:", gkq_atm; print *, "displ_red_qq:", displ_red_qq; print *, "gkq_nu:", gkq_nu
     644                 :             : 
     645                 :             :        ! Write |g|^2 for this q.
     646                 :             :        !if (pert_comm%me == master) then
     647   [ +  -  +  -  :        6720 :        gkq2_nu = gkq_nu(1,:,:,:)**2 + gkq_nu(2,:,:,:)**2
          +  -  -  +  -  
          -  +  +  +  +  
                   +  + ]
     648   [ +  +  -  +  :         588 :        NCF_CHECK(nf90_put_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
                   -  - ]
     649                 :             :        !end if
     650                 :             : 
     651         [ -  + ]:          84 :        if (has_gwan) then
     652                 :             :          ! Interpolate e-ph matrix elements from GWAN.nc at this same (k,q) for comparison.
     653   [ #  #  #  #  :           0 :          ABI_MALLOC(g_atm_wan_local, (nwan_glob, nwan_glob, my_npert, 1))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     654                 :             :          ! The routine already diagonalizes H^W(k) and H^W(k+q) to rotate g to the
     655                 :             :          ! interpolated eigenstate basis, hence it also returns these eigenvalues.
     656                 :             :          call wan%interp_eph_manyq(cryst, 1, qq, kk, g_atm_wan_local, &
     657                 :           0 :                                    out_eigens_k=eig_k_wan, out_eigens_kq=eig_kq_wan)
     658         [ #  # ]:           0 :          if (iq == 1) then
     659   [ #  #  #  #  :           0 :            NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_wan_k"), eig_k_wan, start=[1,ik,spin]))
                   #  # ]
     660                 :             :          end if
     661         [ #  # ]:           0 :          if (ik == 1) then
     662   [ #  #  #  #  :           0 :            NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_wan_kq"), eig_kq_wan(:,1), start=[1,iq,spin]))
                   #  # ]
     663                 :             :          end if
     664                 :             : 
     665   [ #  #  #  #  :           0 :          gkq_atm_wan = zero
             #  #  #  # ]
     666         [ #  # ]:           0 :          do my_ip=1,my_npert
     667                 :           0 :            iglob = wan%my_pert_start + my_ip - 1
     668   [ #  #  #  # ]:           0 :            gkq_atm_wan(1,:,:,iglob) = real(g_atm_wan_local(:,:,my_ip,1), kind=dp)
     669   [ #  #  #  # ]:           0 :            gkq_atm_wan(2,:,:,iglob) = aimag(g_atm_wan_local(:,:,my_ip,1))
     670                 :             :          end do
     671         [ #  # ]:           0 :          if (pert_comm%nproc > 1) call xmpi_sum(gkq_atm_wan, pert_comm%value, ierr)
     672                 :             : 
     673                 :             :          ! Reuses phfreqs/displ_red_qq already computed above (ifc%fourq) for this same q --
     674                 :             :          ! no new gauge issue, same literal-q call already used for the ab-initio side.
     675                 :           0 :          call ephtk_gkknu_from_atm(nwan_glob, nwan_glob, 1, natom, gkq_atm_wan, phfreqs, displ_red_qq, gkq_nu_wan)
     676   [ #  #  #  #  :           0 :          gkq2_nu_wan = gkq_nu_wan(1,:,:,:)**2 + gkq_nu_wan(2,:,:,:)**2
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     677   [ #  #  #  #  :           0 :          NCF_CHECK(nf90_put_var(ncid, vid("gkq2_nu_wan"), gkq2_nu_wan, start=[1,1,1,iq,ik,spin]))
                   #  # ]
     678                 :             : 
     679         [ #  # ]:           0 :          ABI_FREE(g_atm_wan_local)
     680                 :             :        end if
     681                 :             : 
     682         [ -  + ]:          84 :        ABI_FREE(gs1c)
     683         [ -  + ]:          84 :        ABI_FREE(vlocal1)
     684         [ -  + ]:          84 :        ABI_FREE(v1scf)
     685         [ -  + ]:          84 :        ABI_FREE(vlocal_kq)
     686         [ -  + ]:          84 :        ABI_FREE(ph3d_kq)
     687         [ -  + ]:          84 :        ABI_FREE(kpg_kq)
     688         [ -  + ]:          84 :        ABI_FREE(kinpw_kq)
     689         [ -  + ]:          84 :        ABI_FREE(ffnl_kq)
     690         [ -  + ]:          84 :        ABI_FREE(kg_kq)
     691         [ -  + ]:          84 :        ABI_FREE(eig_kq)
     692         [ -  + ]:          84 :        ABI_FREE(cg_kq)
     693         [ -  + ]:          84 :        ABI_FREE(gsc_kq)
     694         [ -  + ]:          84 :        ABI_FREE(h1_kets_kq)
     695                 :         127 :        call gs_ham_kq%free(); call rf_ham_kq%free()
     696                 :             :      end do ! my_iq
     697                 :             : 
     698         [ -  + ]:          43 :      ABI_FREE(vlocal)
     699         [ -  + ]:          43 :      ABI_FREE(vlocal_k)
     700         [ -  + ]:          43 :      ABI_FREE(ph3d_k)
     701         [ -  + ]:          43 :      ABI_FREE(kpg_k)
     702         [ -  + ]:          43 :      ABI_FREE(kinpw_k)
     703         [ -  + ]:          43 :      ABI_FREE(ffnl_k)
     704         [ -  + ]:          43 :      ABI_FREE(kg_k)
     705         [ -  + ]:          43 :      ABI_FREE(eig_k)
     706         [ -  + ]:          43 :      ABI_FREE(cg_k)
     707         [ -  + ]:          43 :      ABI_FREE(gsc_k)
     708                 :          45 :      call gs_ham_k%free()
     709                 :             :    end do ! my_ik
     710                 :             : 
     711         [ -  + ]:           4 :    if (has_gwan) call wan%free()
     712                 :             :  end do ! my_is
     713                 :             : 
     714         [ -  + ]:           2 :  NCF_CHECK(nf90_close(ncid))
     715                 :           2 :  call xmpi_barrier(comm)
     716                 :             : 
     717                 :             :  ! ===========================================
     718                 :             :  ! Write results to ab_out for automatic tests
     719                 :             :  ! ===========================================
     720                 :           2 :  call xmpi_sum(tot_nscf_ierr, comm, ierr)
     721                 :           2 :  tot_nscf_ierr = int(tot_nscf_ierr / dble(pert_comm%nproc))
     722                 :             : 
     723         [ +  - ]:           2 :  if (my_rank == master) then
     724         [ +  - ]:           2 :    if (tot_nscf_ierr == 0) then
     725                 :             :      call wrtout(units, &
     726                 :           2 :        sjoin("Computation of g(k,q) completed. All NSCF runs converged within tolwfr: ", ftoa(dtset%tolwfr)), pre_newlines=1)
     727                 :             :    else
     728         [ #  # ]:           0 :      msg = sjoin("WARNING:", itoa(tot_nscf_ierr), "NSCF runs did not converge within tolwfr: ", ftoa(dtset%tolwfr))
     729         [ #  # ]:           0 :      msg = sjoin(msg, ". Use nbdbuf and/or increase nstep!")
     730                 :           0 :      call wrtout(ab_out, msg)
     731                 :           0 :      ABI_WARNING(msg)
     732                 :             :    end if
     733                 :             : 
     734         [ -  + ]:           2 :    NCF_CHECK(nctk_open_read(ncid, gpath_path, xmpi_comm_self))
     735                 :             : 
     736                 :             :    ! Write k/q wavevectors.
     737                 :           2 :    call wrtout(units, "kpoints:")
     738         [ +  + ]:          45 :    do ik=1, nk_path
     739                 :          45 :      call wrtout(units, sjoin(char(9), itoa(ik), ktoa(kpath%points(:,ik))))
     740                 :             :    end do
     741                 :           2 :    call wrtout(units, "qpoints:")
     742         [ +  + ]:          45 :    do iq=1, nq_path
     743                 :          45 :      call wrtout(units, sjoin(char(9), itoa(iq), ktoa(qpath%points(:,iq))))
     744                 :             :    end do
     745                 :             : 
     746                 :             :    ! Write KS eigenvalues.
     747         [ +  + ]:           2 :    if (nq_path > 1) then
     748   [ -  +  +  -  :           3 :      ABI_MALLOC(eig_kq, (nband))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     749         [ +  + ]:           2 :      do spin=1,nsppol
     750                 :           1 :        call wrtout(units, sjoin(" Energies_kq in eV for spin:", itoa(spin)))
     751         [ +  + ]:          44 :        do iq=1, nq_path
     752   [ +  +  +  +  :          42 :          if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
                   +  + ]
     753   [ +  +  -  +  :          16 :          NCF_CHECK(nf90_get_var(ncid, vid("all_eigens_kq"), eig_kq, start=[1,iq,spin]))
                   -  - ]
     754         [ +  + ]:          17 :          do ii=0,(nband-1)/8
     755   [ +  -  +  + ]:          84 :            write(msg, '(a, 8es16.6)' )' ene:',(eig_kq(band_m) * Ha_eV, band_m=1+ii*8,min(nband,8+ii*8))
     756                 :          54 :            call wrtout(units, msg)
     757                 :             :          end do
     758                 :             :        end do
     759                 :             :      end do
     760         [ -  + ]:           1 :      ABI_FREE(eig_kq)
     761                 :             : 
     762                 :             :    else
     763                 :             :      ! nk_path > 1
     764   [ -  +  +  -  :           3 :      ABI_MALLOC(eig_k, (nband))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     765         [ +  + ]:           2 :      do spin=1,nsppol
     766                 :           1 :        call wrtout(units, sjoin(" Energies_k in eV for spin:", itoa(spin)))
     767         [ +  + ]:          44 :        do ik=1, nk_path
     768   [ +  +  -  +  :         168 :          NCF_CHECK(nf90_get_var(ncid, vid("all_eigens_k"), eig_k, start=[1,ik,spin]))
                   -  - ]
     769   [ +  +  +  +  :          42 :          if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
                   +  + ]
     770         [ +  + ]:          17 :          do ii=0,(nband-1)/8
     771   [ +  -  +  + ]:          84 :            write(msg, '(a, 8es16.6)' )' ene:',(eig_k(band_n) * Ha_eV, band_n=1+ii*8,min(nband,8+ii*8))
     772                 :          54 :            call wrtout(units, msg)
     773                 :             :          end do
     774                 :             :        end do
     775                 :             :      end do
     776         [ -  + ]:           1 :      ABI_FREE(eig_k)
     777                 :             :    end if
     778                 :             : 
     779                 :             :    ! Save g^2 in nc format without any average. This operation will be performed by AbiPy (need ph freqs and eigenergies)
     780                 :           2 :    call wrtout(units, " Writing sqrt(1/N_b^2 \sum_{mn} |g_{mn,nu}(k, q)|^2) in meV for testing purpose.", pre_newlines=2)
     781                 :           2 :    write(msg, "(1x,4(a5,1x),a16)") "nu","iq", "ik", "spin", "|g| in meV"
     782                 :           2 :    call wrtout(units, msg)
     783                 :             : 
     784         [ +  + ]:           4 :    do spin=1,nsppol
     785         [ +  + ]:          47 :      do ik=1, nk_path
     786   [ +  +  +  +  :          43 :        if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
                   +  + ]
     787         [ +  + ]:          53 :        do iq=1, nq_path
     788   [ +  +  +  +  :          46 :          if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
                   +  + ]
     789   [ +  +  -  +  :          56 :          NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
                   -  - ]
     790         [ +  + ]:          99 :          do nu=1,natom3
     791   [ +  +  +  + ]:         624 :            write(msg, "(1x,4(i5,1x),es16.6)") nu, iq, ik, spin, sqrt(sum(gkq2_nu(:,:, nu)) / nb_in_g**2) * Ha_meV
     792                 :          94 :            call wrtout(units, msg)
     793                 :             :          end do
     794                 :             :        end do ! iq
     795                 :             :      end do ! ik
     796                 :             :    end do ! spin
     797                 :             : 
     798         [ -  + ]:           2 :    if (has_gwan) then
     799                 :             :      call wrtout(units, &
     800                 :           0 :        " Writing sqrt(1/N^2 sum |g|^2): ab-initio vs Wannier-interpolated (gauge-invariant trace), meV.", pre_newlines=2)
     801                 :           0 :      write(msg, "(1x,4(a5,1x),2(a18,1x))") "nu","iq","ik","spin", "|g|_abinitio(meV)", "|g|_wannier(meV)"
     802                 :           0 :      call wrtout(units, msg)
     803         [ #  # ]:           0 :      do spin=1,nsppol
     804         [ #  # ]:           0 :        do ik=1, nk_path
     805   [ #  #  #  #  :           0 :          if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
                   #  # ]
     806         [ #  # ]:           0 :          do iq=1, nq_path
     807   [ #  #  #  #  :           0 :            if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
                   #  # ]
     808   [ #  #  #  #  :           0 :            NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
                   #  # ]
     809   [ #  #  #  #  :           0 :            NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu_wan"), gkq2_nu_wan, start=[1,1,1,iq,ik,spin]))
                   #  # ]
     810         [ #  # ]:           0 :            do nu=1,natom3
     811                 :           0 :              write(msg, "(1x,4(i5,1x),2(es18.6,1x))") nu, iq, ik, spin, &
     812   [ #  #  #  #  :           0 :                sqrt(sum(gkq2_nu(:,:,nu)) / nb_in_g**2) * Ha_meV, sqrt(sum(gkq2_nu_wan(:,:,nu)) / nwan_glob**2) * Ha_meV
             #  #  #  # ]
     813                 :           0 :              call wrtout(units, msg)
     814                 :             :            end do
     815                 :             :          end do ! iq
     816                 :             :        end do ! ik
     817                 :             :      end do ! spin
     818                 :             :    end if
     819                 :             : 
     820         [ -  + ]:           2 :    NCF_CHECK(nf90_close(ncid))
     821                 :             :  end if ! master
     822                 :             : 
     823                 :             :  ! Free memory.
     824         [ -  + ]:           2 :  ABI_FREE(my_ik_inds)
     825         [ -  + ]:           2 :  ABI_FREE(my_iq_inds)
     826         [ -  + ]:           2 :  ABI_FREE(gvnlx1)
     827         [ -  + ]:           2 :  ABI_FREE(grad_berry)
     828         [ -  + ]:           2 :  ABI_FREE(qmap_symrec)
     829         [ -  + ]:           2 :  ABI_FREE(gkq_atm)
     830         [ -  + ]:           2 :  ABI_FREE(gkq_nu)
     831         [ -  + ]:           2 :  ABI_FREE(gkq2_nu)
     832         [ -  + ]:           2 :  if (has_gwan) then
     833         [ #  # ]:           0 :    ABI_FREE(gkq_atm_wan)
     834         [ #  # ]:           0 :    ABI_FREE(gkq_nu_wan)
     835         [ #  # ]:           0 :    ABI_FREE(gkq2_nu_wan)
     836         [ #  # ]:           0 :    ABI_FREE(eig_k_wan)
     837         [ #  # ]:           0 :    ABI_FREE(eig_kq_wan)
     838                 :             :  end if
     839         [ -  + ]:           2 :  ABI_FREE(displ_cart)
     840         [ -  + ]:           2 :  ABI_FREE(displ_red_qq)
     841         [ -  + ]:           2 :  ABI_FREE(my_spins)
     842                 :             : 
     843                 :           2 :  call pawcprj_free(cwaveprj0)
     844   [ +  -  -  +  :           2 :  ABI_FREE(cwaveprj0)
          -  -  -  -  -  
                      + ]
     845         [ +  + ]:           4 :  do my_is=1,my_nspins
     846                 :           4 :    call comm_my_is(my_is)%free()
     847                 :             :  end do
     848         [ -  + ]:           2 :  ABI_FREE(comm_my_is)
     849                 :             : 
     850                 :           2 :  call qpath%free(); call kpath%free(); call ucache_k%free(); call ucache_kq%free()
     851                 :           2 :  call qpt_comm%free(); call kpt_comm%free(); call pert_comm%free(); call nscf%free()
     852                 :             : 
     853   [ -  +  -  +  :           8 :  call cwtime_report(" eph_path: MPI barrier before returning.", cpu_all, wall_all, gflops_all, end_str=ch10, comm=comm)
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  -  
          -  -  -  -  +  
             -  +  -  + ]
     854                 :             :  !stop
     855                 :             : 
     856                 :             : contains
     857                 :         324 :  integer function vid(var_name)
     858                 :             :    character(len=*),intent(in) :: var_name
     859                 :         324 :    vid = nctk_idname(ncid, var_name)
     860                 :             :  end function vid
     861                 :             : 
     862                 :             : end subroutine eph_path_run
     863                 :             : !!***
     864                 :             : 
     865                 :             : end module m_eph_path
     866                 :             : !!***
        

Generated by: LCOV version 2.3-1