LCOV - code coverage report
Current view: top level - src/72_response - m_dvdb.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 64.3 % 2340 1505
Test Date: 2026-09-21 19:39:32 Functions: 76.0 % 50 38

            Line data    Source code
       1              : !!****m* ABINIT/m_dvdb
       2              : !! NAME
       3              : !!  m_dvdb
       4              : !!
       5              : !! FUNCTION
       6              : !!  Objects and methods to extract data from the DVDB file.
       7              : !!  The DVDB file is Fortran binary file with a collection of DFPT potentials
       8              : !!  associated to the different phonon perturbations (idir, ipert, qpt).
       9              : !!  DVDB files are produced with the `mrgdv` utility and used in the EPH code
      10              : !!  to compute the matrix elements: <k+q| dvscf_{idir, ipert, qpt} |k>.
      11              : !!
      12              : !! COPYRIGHT
      13              : !! Copyright (C) 2009-2026 ABINIT group (MG, GA)
      14              : !! This file is distributed under the terms of the
      15              : !! GNU General Public License, see ~abinit/COPYING
      16              : !! or http://www.gnu.org/copyleft/gpl.txt .
      17              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
      18              : !!
      19              : !! TODO
      20              : !!  - Check spin and MPI-parallelism. Can we distribute nsppol?
      21              : !!
      22              : !! SOURCE
      23              : 
      24              : #if defined HAVE_CONFIG_H
      25              : #include "config.h"
      26              : #endif
      27              : 
      28              : #include "abi_common.h"
      29              : 
      30              : module m_dvdb
      31              : 
      32              :  use defs_basis
      33              :  use m_abicore
      34              :  use m_errors
      35              :  use m_xmpi
      36              :  use m_nctk
      37              :  use m_sort
      38              :  use netcdf
      39              :  use m_hdr
      40              :  use m_ddb
      41              :  use m_ddb_hdr
      42              :  use m_dtset
      43              :  use m_krank
      44              :  use m_xcdata
      45              : 
      46              :  use defs_abitypes,   only : mpi_type
      47              :  use m_fstrings,      only : strcat, sjoin, itoa, ktoa, ltoa, ftoa, yesno, endswith
      48              :  use m_time,          only : cwtime, cwtime_report, sec2str, timab
      49              :  use m_io_tools,      only : open_file, file_exists, delete_file
      50              :  use m_numeric_tools, only : wrap2_pmhalf, vdiff_t, l2int
      51              :  use m_matrix,        only : mati3inv, matr3inv
      52              :  use m_symtk,         only : littlegroup_q
      53              :  use m_geometry,      only : littlegroup_pert, irreducible_set_pert, mkradim, xcart2xred
      54              :  use m_dynmat,        only : canat9, get_bigbox_and_weights
      55              :  use m_copy,          only : alloc_copy
      56              :  use m_mpinfo,        only : destroy_mpi_enreg, initmpi_seq
      57              :  use m_ioarr,         only : read_rhor
      58              :  use m_fftcore,       only : ngfft_seq
      59              :  use m_fft_mesh,      only : rotate_fft_mesh, times_eigr, times_eikr, ig2gfft, get_gfft, calc_ceikr, calc_eigr
      60              :  use m_fft,           only : fourdp, zerosym
      61              :  use m_crystal,       only : crystal_t
      62              :  use m_kpts,          only : kpts_ibz_from_kptrlatt, listkk, kpts_map, kpts_timrev_from_kptopt
      63              :  use m_spacepar,      only : symrhg, setsym
      64              :  use m_fourier_interpol,only : fourier_interpol_seq
      65              :  use m_pawrhoij,      only : pawrhoij_type
      66              :  use m_dfpt_mkvxc,     only : dfpt_mkvxc
      67              : 
      68              :  implicit none
      69              : 
      70              :  private
      71              : !!***
      72              : 
      73              :  ! Version 1: header + vscf1(r)
      74              :  ! Version 2: header + vscf1(r) + record with rhog1(G=0)
      75              :  integer,public,parameter :: dvdb_last_version = 2
      76              : 
      77              :  integer,private,parameter :: DVDB_NOMODE    = 0
      78              :  integer,private,parameter :: DVDB_READMODE  = 1
      79              :  integer,private,parameter :: DVDB_WRITEMODE = 2
      80              : 
      81              : !----------------------------------------------------------------------
      82              : 
      83              : !!****t* m_dvdb/dvdb_t
      84              : !! NAME
      85              : !!  dvdb_t
      86              : !!
      87              : !! FUNCTION
      88              : !!  Database of DFPT results. The database contains `numv1` perturbations
      89              : !!  and the corresponding first order local potentials in real space on the FFT mesh.
      90              : !!  Provides methods to Fourier interpolate the potentials including the
      91              : !!  treatment of long-range behaviour in the FT interpolation in polar semiconductors.
      92              : !!  Note that one can have different FFT meshes for the different perturbations.
      93              : !!
      94              : !! NOTES
      95              : !!  natom, nspden, nspinor, and usepaw are global variables in the sense that it is not possible to add
      96              : !!  new entries to the database if these dimensions differ from the global ones.
      97              : !!
      98              : !! SOURCE
      99              : 
     100              :  type,public :: dvdb_t
     101              : 
     102              :   integer :: fh
     103              :    ! file handle
     104              :    ! Fortran unit number if iomode==IO_MODE_FORTRAN
     105              :    ! MPI file handler if iomode==IO_MODE_MPI
     106              : 
     107              :   integer :: fform
     108              :   ! File format
     109              : 
     110              :   integer :: comm
     111              :   ! Global MPI communicator used for IO.
     112              : 
     113              :   integer :: gpu_option = 0
     114              :   ! Input variable
     115              : 
     116              :   integer :: comm_rpt = xmpi_comm_self
     117              :    ! MPI communicator used to distributed R-points.
     118              : 
     119              :   integer :: nprocs_rpt = 1
     120              :    ! Number of cpus for parallelism over R-points.
     121              : 
     122              :   integer :: me_rpt = 0
     123              :    ! My rank in comm_rpt.
     124              : 
     125              :   integer :: comm_pert = xmpi_comm_self
     126              :    ! MPI communicator for parallelism over atomic perturbations.
     127              : 
     128              :   integer :: nprocs_pert = 1
     129              :    ! Number of cpus for parallelism over atomic perturbations.
     130              : 
     131              :   integer :: me_pert = 0
     132              :    ! My rank in comm over atomic perturbations.
     133              : 
     134              :   integer :: my_npert
     135              :    ! Number of atomic perturbations or phonon modes treated by this MPI rank
     136              : 
     137              :   integer,allocatable :: my_pinfo(:,:)
     138              :     ! my_pinfo(3, my_npert)
     139              :     ! my_pinfo(1, ip) gives the `idir` index of the ip-th perturbation.
     140              :     ! my_pinfo(2, ip) gives the `ipert` index of the ip-th perturbation.
     141              :     ! my_pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3
     142              : 
     143              :   integer,allocatable :: pert_table(:,:)
     144              :     ! pert_table(2, natom3)
     145              :     !     pert_table(1, npert): rank of the processor treating this atomic perturbation.
     146              :     !     pert_table(2, npert): imyp index in my_pinfo table, -1 if this rank is not treating ipert.
     147              : 
     148              :   integer :: version
     149              :   ! File format version read from file.
     150              : 
     151              :   integer :: iomode = IO_MODE_FORTRAN
     152              :   ! Method used to access the DVDB file:
     153              :   !   IO_MODE_FORTRAN for usual Fortran IO routines
     154              :   !   IO_MODE_MPI if MPI/IO routines.
     155              : 
     156              :   integer :: rw_mode = DVDB_NOMODE
     157              :    ! (Read|Write) mode
     158              : 
     159              :   integer :: current_fpos
     160              :   ! The current position of the file pointer used for sequential access with Fortran-IO
     161              : 
     162              :   integer :: numv1
     163              :   ! Number of v1 potentials present in file.
     164              : 
     165              :   integer :: nqpt
     166              :   ! Number of q-points (usually the IBZ)
     167              : 
     168              :   integer :: natom
     169              :    ! Number of atoms
     170              : 
     171              :   integer :: natom3
     172              :    ! 3 * natom
     173              : 
     174              :   integer :: nspden
     175              :    ! Number of spin density components
     176              : 
     177              :   integer :: nsppol
     178              :    ! Number of spin polarizations.
     179              : 
     180              :   integer :: nspinor
     181              :    ! Number of spinor components.
     182              : 
     183              :   integer :: usepaw
     184              :    ! 1 if PAW calculation, 0 otherwise
     185              : 
     186              :   integer :: mpert
     187              :    ! Maximum number of perturbations
     188              : 
     189              :   integer :: my_nrpt = 0
     190              :   ! Number of real space points used for Fourier interpolation treated by this MPI rank.
     191              : 
     192              :   integer :: nrtot = 0
     193              :   ! Total Number of real space points used for Fourier interpolation.
     194              : 
     195              :   integer :: prtvol = 0
     196              :    ! Verbosity level
     197              : 
     198              :   integer :: brav = 1
     199              :   ! Option for the sampling of the BZ (input variable, the same option is stored in ifc_t)
     200              : 
     201              :   real(dp) :: qdamp = 0.1_dp
     202              :    ! Exponential damping used in the Fourier transform of the long-range potentials
     203              :    ! Use negative value to deactivate damping.
     204              : 
     205              :   logical :: debug = .False.
     206              :    ! Debug flag
     207              : 
     208              :   logical :: has_dielt = .False.
     209              :   ! True if the dielectric tensor is available.
     210              : 
     211              :   logical :: has_zeff = .False.
     212              :   ! True if Born effective charges are available.
     213              : 
     214              :   logical :: has_quadrupoles = .False.
     215              :   ! True if quadrupoles are available.
     216              : 
     217              :   logical :: has_efield = .False.
     218              :   ! True if electric field perturbations are available.
     219              : 
     220              :   integer :: add_lr = 1
     221              :    ! Flag defining the treatment of the long range component in the interpolation of the DFPT potentials.
     222              :    !
     223              :    ! 0 --> No treatment
     224              :    ! 1 --> Remove LR model when building W(R,r). Add it back after W(R,r) --> v(q) Fourier interpolation
     225              :    !       This is the standard approach for polar materials.
     226              :    ! -1 --> Remove LR model when building W(R,r). DO NOT reintroduce it after Fourier interpolation.
     227              :    !       This procedure should be used for homopolar materials with (spurious) non-zero BECS
     228              :    !       in order to remove the long range component from the DFPT potentials.
     229              :    ! 2 --> Similar to 1 but include only the dipole part. Q* are set to zero even if the DDB file contains them.
     230              :    ! 4,5,6,7 --> Use model for the LR part only.
     231              :    !        4: Use dipole + quadrupole part (if available)
     232              :    !        5: Use dipole part only.
     233              :    !        6: Use quadrupole part only.
     234              :    !        7: Use electric field only.
     235              : 
     236              :   integer :: symv1 = 0
     237              :    ! Flag for the symmetrization of v1 potentials.
     238              :    ! 0 --> No symmetrization
     239              :    ! 1 --> Symmetrization in real space
     240              :    ! 2 --> Call v1phq_complete after interpolation of the potentials in ftinterp_qpt
     241              : 
     242              :   integer :: rspace_cell = 0
     243              :    ! Flag defining the algorithm for generating the list of R-points and the weights used to go from W(r,R) to v1scf(r,q)
     244              :    ! 0 --> Use unit supercell for R space. All weights set to 1.
     245              :    ! 1 --> Use Wigner-Seitz super cell and atom dependent weights (same algo as for dynmat)
     246              : 
     247              :   character(len=fnlen) :: path = ABI_NOFILE
     248              :    ! File name of the DVDB file.
     249              : 
     250              :   real(dp) :: dielt(3, 3) = zero
     251              :    ! Dielectric tensor in Cartesian coordinates.
     252              :    ! Used to deal with the long-range component in the Fourier interpolation.
     253              : 
     254              :   integer,allocatable :: pos_dpq(:,:,:)
     255              :    ! pos_dpq(3, mpert, nqpt)
     256              :    ! The position of the (idir, ipert, iqpt) potential in the file (in units of POT1 blocks)
     257              :    ! 0 if the corresponding entry is not available.
     258              : 
     259              :   integer,allocatable :: cplex_v1(:)
     260              :   ! cplex_v1(numv1)
     261              :   ! The value of cplex for each v1(cplex*nfft, nspden) potential
     262              :   ! 2 if the potential is complex, 1 if real (q==Gamma)
     263              : 
     264              :   integer,allocatable :: symq_table(:,:,:,:)
     265              :   ! symq(4,2,nsym,nqpt)
     266              :   ! Table computed by littlegroup_q for all q-points found in the DVDB.
     267              :   !   three first numbers define the G vector;
     268              :   !   fourth number is zero if the q-vector is not preserved, is 1 otherwise
     269              :   !   second index is one without time-reversal symmetry, two with time-reversal symmetry
     270              : 
     271              :   integer :: ngfft(18) = -1
     272              :    ! Info on the FFT to be used for the potentials.
     273              : 
     274              :   integer,allocatable :: iv_pinfoq(:,:)
     275              :    !iv_pinfoq(4, numv1)
     276              :    !  iv_pinfoq(1, iv1) gives the `idir` index of the iv1 potential
     277              :    !  iv_pinfoq(2, iv1) gives the `ipert` index of the iv1 potential
     278              :    !  iv_pinfoq(3, iv1) gives `pertcase`=idir + (ipert-1)*3
     279              :    !  iv_pinfoq(4, iv1) gives the `iqpt` index of the iv1 potential
     280              : 
     281              :   integer,allocatable :: ngfft3_v1(:,:)
     282              :    ! ngfft3_v1(3, numv1)
     283              :    ! The FFT mesh used for each v1 potential (the one used to store data in the file).
     284              : 
     285              :   integer,allocatable :: my_irpt2tot(:)
     286              :   ! Mapping my_irpt index to full list of R-points.
     287              : 
     288              :   real(dp),allocatable :: qpts(:,:)
     289              :    ! qpts(3,nqpt)
     290              :    ! List of q-points in reduced coordinates.
     291              : 
     292              :   real(dp),allocatable :: my_rpt(:,:)
     293              :   ! my_rpt(3, my_nrpt)
     294              :   ! Real space points for Fourier interpolation (MPI distributed if nprocs_rpt > 1)
     295              : 
     296              :   real(kind=sp),allocatable :: wsr(:,:,:,:,:)
     297              :   ! DFPT potential in the real space supercell representation.
     298              :   ! wsr(1, my_nrpt, nfft, nspden, my_npert)
     299              :   ! NOTE kind=sp to save memory as much as possible.
     300              :   !
     301              :   ! TODO: Use MPI shared window
     302              : 
     303              :   real(dp),allocatable :: my_wratm(:,:)
     304              :   ! my_wratm(my_nrpt, minatom:maxatom)
     305              :   ! Weight for the FT associated to the atom and the R vector.
     306              : 
     307              :   real(dp),allocatable :: rhog1_g0(:,:)
     308              :   ! rhog1_g0(2, numv1)
     309              :   ! G=0 component of rhog1. Used to treat the long range component in (polar) semiconductors.
     310              :   ! NB: For the time being, this quantity is not used. Long range term is treated with Verdi's model and quadrupoles
     311              : 
     312              :   real(dp),allocatable :: zeff(:,:,:)
     313              :   ! zeff(3, 3, natom)
     314              :   ! Effective charges on each atom, versus electric field and atomic displacement in Cartesian coordinates.
     315              :   ! Used to deal with the long-range component in the Fourier interpolation.
     316              : 
     317              :   real(dp),allocatable :: zeff_raw(:,:,:)
     318              :   ! Raw Effective charges i.e. values before enforcing the charge-neutrality condition.
     319              : 
     320              :   real(dp),allocatable :: qstar(:,:,:,:)
     321              :   ! qstar(3, 3, 3, natom)
     322              :   ! dynamical quadrupole in Cartesian coordinates.
     323              :   ! First two dimension are associated to the q-point, then atomic perturbation in Cart coords.
     324              : 
     325              :   real(dp),allocatable :: v1r_efield(:,:,:)
     326              :   ! v1r_efield(nfft, 3, nspden)
     327              :   ! First order potentials due to the three different directions of the electric field perturbation.
     328              :   ! Potentials are in r-space
     329              : 
     330              :   type(crystal_t) :: cryst
     331              :   ! Crystalline structure read from the the DVDB file.
     332              : 
     333              :   type(hdr_type) :: hdr_ref
     334              :   ! Header associated to the first potential in the DVDB. Used to backspace.
     335              :   ! Gives the number of Fortran records required to backspace the header
     336              :   ! Assume all headers with same fform and same basic dimensions e.g. npsp
     337              : 
     338              :   type(mpi_type) :: mpi_enreg
     339              :   ! Internal object used to call fourdp and other GS/DFPT routines
     340              : 
     341              :  contains
     342              : 
     343              :    procedure :: init => dvdb_init                !
     344              :    ! Create new object.
     345              : 
     346              :    procedure :: open_read => dvdb_open_read
     347              :    ! Open the file in read-only mode.
     348              : 
     349              :    procedure :: close => dvdb_close
     350              :    ! Close the DVDB file.
     351              : 
     352              :    procedure :: free => dvdb_free
     353              :    ! Release the memory allocated and close the file.
     354              : 
     355              :    procedure :: has_fields => dvdb_has_fields
     356              :    ! Check whether the DVDB database stores first-order potentials or first-order densities
     357              : 
     358              :    procedure :: print => dvdb_print
     359              :    ! Print info on object.
     360              : 
     361              :    procedure :: findq => dvdb_findq
     362              :    ! Returns the index of the q-point.
     363              : 
     364              :    procedure :: find_qpts => dvdb_find_qpts
     365              :    ! Returns the index of a list of q-points.
     366              : 
     367              :    procedure :: need_ftinterp => dvdb_need_ftinterp
     368              :    ! Check whether input list of q-points requires Fourier interpolation.
     369              : 
     370              :    procedure :: set_pert_distrib => dvdb_set_pert_distrib
     371              :    !  Activate parallelism over perturbations
     372              : 
     373              :    procedure :: read_onev1 => dvdb_read_onev1
     374              :    ! Read and return the DFPT potential for given (idir, ipert, iqpt).
     375              : 
     376              :    procedure :: readsym_allv1 => dvdb_readsym_allv1
     377              :    ! Read and return all the 3*natom DFPT potentials (either from file or symmetrized)
     378              : 
     379              :    procedure :: readsym_qbz => dvdb_readsym_qbz
     380              :    ! Reconstruct the DFPT potential for a q-point in the BZ from its symmetrical image in the IBZ.
     381              : 
     382              :    procedure :: read_vxc1_qbz => dvdb_read_vxc1_qbz
     383              :    ! Compute the first-order change of exchange-correlation potential
     384              :    ! for a q-point in the BZ starting from its symmetrical image in the IBZ.
     385              : 
     386              :    procedure :: list_perts => dvdb_list_perts
     387              :    ! Check if all the (phonon) perts are available taking into account symmetries.
     388              : 
     389              :    procedure :: ftinterp_setup => dvdb_ftinterp_setup
     390              :    ! Prepare the internal tables for Fourier interpolation.
     391              : 
     392              :    procedure :: get_maxw => dvdb_get_maxw
     393              :    ! Compute max_r |W(R,r)|
     394              : 
     395              :    procedure :: ftinterp_qpt => dvdb_ftinterp_qpt
     396              :    ! Fourier interpolation of potentials for given q-point
     397              : 
     398              :    procedure :: get_ftqbz => dvdb_get_ftqbz
     399              :    ! Retrieve Fourier interpolated potential for a given q-point in the BZ.
     400              :    ! Use cache to reduce number of slow FTs.
     401              : 
     402              :    procedure :: get_vxc1_ftqbz => dvdb_get_vxc1_ftqbz
     403              :    ! Retrieve Fourier interpolated first-order change of exchange-correlation
     404              :    ! potential v1xc for a given q-point in the BZ.
     405              : 
     406              :    procedure :: get_v1r_long_range => dvdb_get_v1r_long_range
     407              :    ! Long-range part of the phonon potential
     408              : 
     409              :    procedure :: load_ddb => dvdb_load_ddb
     410              :    ! Load information about the Born effective charges and dielectric tensor from a DDB file
     411              : 
     412              :    procedure :: interpolate_v1scf => dvdb_interpolate_v1scf
     413              :    ! Fourier interpolation of the phonon potentials
     414              : 
     415              :    procedure :: get_v1scf_rpt => dvdb_get_v1scf_rpt
     416              :    ! Fourier transform of the phonon potential from qpt to R
     417              : 
     418              :    procedure :: get_v1scf_qpt => dvdb_get_v1scf_qpt
     419              :    ! Fourier transform of the phonon potential from R to qpt
     420              : 
     421              :    procedure :: load_efield => dvdb_load_efield
     422              :    ! Load the potential due to the Electric field.
     423              : 
     424              :    procedure :: interpolate_and_write => dvdb_interpolate_and_write
     425              :    ! Interpolate the phonon potentials and write a new DVDB file.
     426              : 
     427              :    procedure :: qdownsample => dvdb_qdownsample
     428              :    ! Downsample the q-mesh. Produce new DVDB file
     429              : 
     430              :    procedure :: write_v1qavg => dvdb_write_v1qavg
     431              :    ! Computes the average over the unit cell of the periodic part of the DFPT potentials
     432              :    ! as a function of the q-point and the corresponding quantity obtained with the model for the LR part.
     433              : 
     434              :  end type dvdb_t
     435              : 
     436              :  ! Utilities
     437              :  public :: dvdb_merge_files        ! Merge a list of POT1 files.
     438              : 
     439              :  ! Debugging tools. These functions are interfaced with mrgdv. Use mrgdv --help to access the documentation
     440              :  public :: dvdb_test_v1rsym        ! Check symmetries in real-space of the DFPT potentials.
     441              :  public :: dvdb_test_v1complete    ! Test the symmetrization of the DFPT potentials.
     442              :  public :: dvdb_test_ftinterp      ! Test the Fourier interpolation of DFPT potentials.
     443              :  public :: dvdb_test_symcheck      ! Test cross-q-point symmetry consistency of the FT interpolation.
     444              :  public :: dvdb_test_symcheck_native ! Same test but on two literal, non-interpolated q-points.
     445              : 
     446              : !----------------------------------------------------------------------
     447              : 
     448           80 :  integer,private,parameter :: pot1_fforms(2) = [109, 111], den1_fforms(1) = [54]
     449              : 
     450              : contains
     451              : !!***
     452              : 
     453              : !----------------------------------------------------------------------
     454              : 
     455              : !!****f* m_dvdb/dvdb_init
     456              : !! NAME
     457              : !!  dvdb_init
     458              : !!
     459              : !! FUNCTION
     460              : !!  Initialize the object from file. This is a COLLECTIVE procedure that must be called
     461              : !!  by each process in the MPI communicator comm.
     462              : !!  We don't pass dtset because in mrgdvd, we need to build an instance and dtset is not available there.
     463              : !!
     464              : !! INPUTS
     465              : !!   path=DVDB Filename.
     466              : !!   comm=MPI communicator.
     467              : !!
     468              : !! SOURCE
     469              : 
     470          116 : subroutine dvdb_init(new, path, gpu_option, comm)
     471              : 
     472              : !Arguments ------------------------------------
     473              : !scalars
     474              :  class(dvdb_t),intent(out) :: new
     475              :  character(len=*),intent(in) :: path
     476              :  integer,intent(in) :: gpu_option, comm
     477              : 
     478              : !Local variables-------------------------------
     479              : !scalars
     480              :  integer,parameter :: master = 0
     481              :  integer :: iv1,ii,ierr,unt,fform,nqpt,iq,iq_found,cplex,trev_q
     482              :  integer :: idir,ipert,my_rank, nprocs, iatom, pertcase
     483              :  real(dp) :: cpu, wall, gflops
     484              :  character(len=500) :: msg
     485          116 :  type(hdr_type) :: hdr1
     486              : !arrays
     487          116 :  integer,allocatable :: tmp_pos(:,:,:)
     488              :  real(dp) :: tsec(2)
     489          116 :  real(dp),allocatable :: tmp_qpts(:,:)
     490              : !************************************************************************
     491              : 
     492              :  ! Keep track of total time spent.
     493          116 :  call timab(1800, 1, tsec)
     494              : 
     495          116 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     496          116 :  new%path = path; new%comm = comm; new%iomode = IO_MODE_FORTRAN
     497          116 :  new%gpu_option = gpu_option
     498              : 
     499          116 :  call wrtout(std_out, sjoin("- Analyzing DVDB file: ", path, "..."))
     500          116 :  call cwtime(cpu, wall, gflops, "start")
     501              : 
     502              :  ! Master reads the header and builds useful tables
     503          116 :  if (my_rank == master) then
     504              : 
     505          116 :    if (open_file(path, msg, newunit=unt, form="unformatted", status="old", action="read") /= 0) then
     506            0 :      ABI_ERROR(msg)
     507              :    end if
     508          116 :    read(unt, err=10, iomsg=msg) new%version
     509          116 :    read(unt, err=10, iomsg=msg) new%numv1
     510              : 
     511              :    ! Get important dimensions from the first header and rewind the file.
     512          116 :    call new%hdr_ref%fort_read(unt, new%fform)
     513          116 :    if (dvdb_check_fform(new%fform, "read_dvdb", msg) /= 0) then
     514            0 :      ABI_ERROR(sjoin("While reading:", path, ch10, msg))
     515              :    end if
     516          116 :    if (new%debug) call new%hdr_ref%echo(new%fform, 4, unit=std_out)
     517              : 
     518          116 :    rewind(unt)
     519          116 :    read(unt, err=10, iomsg=msg)
     520          116 :    read(unt, err=10, iomsg=msg)
     521              : 
     522              :    ! The code below must be executed by the other procs if MPI.
     523          116 :    new%natom = new%hdr_ref%natom
     524          116 :    new%natom3 = 3 * new%hdr_ref%natom
     525          116 :    new%nspden = new%hdr_ref%nspden
     526          116 :    new%nsppol = new%hdr_ref%nsppol
     527          116 :    new%nspinor = new%hdr_ref%nspinor
     528          116 :    new%usepaw = new%hdr_ref%usepaw
     529          116 :    ABI_CHECK(new%usepaw == 0, "PAW not yet supported")
     530              : 
     531              :    ! TODO: Write function to return mpert from natom!
     532          116 :    new%mpert = new%natom + 6
     533              : 
     534          348 :    ABI_MALLOC(tmp_qpts, (3, new%numv1))
     535          464 :    ABI_MALLOC(tmp_pos, (3, new%mpert, new%numv1))
     536        67979 :    tmp_pos = 0
     537              : 
     538          348 :    ABI_MALLOC(new%cplex_v1, (new%numv1))
     539          348 :    ABI_MALLOC(new%ngfft3_v1, (3, new%numv1))
     540          348 :    ABI_MALLOC(new%iv_pinfoq, (4, new%numv1))
     541          348 :    ABI_MALLOC(new%rhog1_g0, (2, new%numv1))
     542              : 
     543          116 :    nqpt = 0
     544         2195 :    do iv1=1,new%numv1
     545         2079 :      call hdr1%fort_read(unt, fform)
     546         2079 :      if (dvdb_check_fform(fform, "read_dvdb", msg) /= 0) then
     547            0 :        ABI_ERROR(sjoin("While reading hdr of v1 potential of index:", itoa(iv1), ch10, msg))
     548              :      end if
     549              : 
     550              :      ! Save cplex and FFT mesh associated to this perturbation.
     551         2079 :      cplex = 2; if (hdr1%qptn(1)**2+hdr1%qptn(2)**2+hdr1%qptn(3)**2<1.d-14) cplex = 1
     552         2079 :      new%cplex_v1(iv1) = cplex
     553         8316 :      new%ngfft3_v1(:, iv1) = hdr1%ngfft(:3)
     554              : 
     555              :      ! Skip the records with v1.
     556         4158 :      do ii=1,hdr1%nspden
     557         4158 :        read(unt, err=10, iomsg=msg)
     558              :      end do
     559              :      ! Read rhog1_g0 (if available)
     560         6237 :      new%rhog1_g0(:, iv1) = zero
     561         2079 :      if (new%version > 1) read(unt, err=10, iomsg=msg) new%rhog1_g0(:, iv1)
     562              : 
     563              :      ! Check whether this q-point is already in the list.
     564              :      ! Assume qpoints are grouped so invert the iq loop for better performance.
     565              :      ! This is gonna be slow if lots of q-points and perturbations are not grouped.
     566         2079 :      iq_found = 0
     567         4629 :      do iq=nqpt,1,-1
     568         9353 :        if (all(abs(hdr1%qptn - tmp_qpts(:,iq)) < tol14)) then
     569              :          iq_found = iq; exit
     570              :        end if
     571              :      end do
     572              : 
     573              :      ! pertcase = idir + (ipert-1)*3 where ipert=iatom in the interesting cases
     574         2079 :      idir = mod(hdr1%pertcase-1, 3) + 1
     575         2079 :      ipert = (hdr1%pertcase - idir) / 3 + 1
     576              : 
     577              :      ! Increment nqpt is new q-points and update tmp_pos
     578         2079 :      if (iq_found == 0) then
     579          682 :        nqpt = nqpt + 1
     580         2728 :        tmp_qpts(:, nqpt) = hdr1%qptn
     581              :        iq_found = nqpt
     582              :      end if
     583         2079 :      tmp_pos(idir, ipert, iq_found) = iv1
     584        10395 :      new%iv_pinfoq(:,iv1) = [idir, ipert, hdr1%pertcase, iq_found]
     585              : 
     586         2195 :      call hdr1%free()
     587              :    end do
     588              : 
     589              :    ! Allocate arrays with correct nqpt dimension
     590          116 :    new%nqpt = nqpt
     591          348 :    ABI_MALLOC(new%qpts, (3, nqpt))
     592         2960 :    new%qpts = tmp_qpts(:,1:nqpt)
     593          116 :    ABI_FREE(tmp_qpts)
     594              : 
     595          464 :    ABI_MALLOC(new%pos_dpq, (3, new%mpert, nqpt))
     596        22342 :    new%pos_dpq = tmp_pos(:, :, 1:nqpt)
     597          116 :    ABI_FREE(tmp_pos)
     598              : 
     599          116 :    close(unt)
     600              :  end if
     601              : 
     602              :  ! Master broadcasts data.
     603          116 :  if (xmpi_comm_size(comm) > 1) then
     604            0 :    call xmpi_bcast(new%version, master, comm, ierr)
     605            0 :    call xmpi_bcast(new%fform, master, comm, ierr)
     606            0 :    call xmpi_bcast(new%numv1, master, comm, ierr)
     607            0 :    call xmpi_bcast(new%nqpt, master, comm, ierr)
     608            0 :    call new%hdr_ref%bcast(master, my_rank, comm)
     609              : 
     610            0 :    new%natom = new%hdr_ref%natom
     611            0 :    new%natom3 = 3 * new%hdr_ref%natom
     612            0 :    new%nspden = new%hdr_ref%nspden
     613            0 :    new%nsppol = new%hdr_ref%nsppol
     614            0 :    new%nspinor = new%hdr_ref%nspinor
     615            0 :    new%usepaw = new%hdr_ref%usepaw
     616            0 :    new%mpert = new%natom + 6
     617              : 
     618            0 :    if (my_rank /= master) then
     619            0 :      ABI_MALLOC(new%cplex_v1, (new%numv1))
     620            0 :      ABI_MALLOC(new%ngfft3_v1, (3, new%numv1))
     621            0 :      ABI_MALLOC(new%iv_pinfoq, (4, new%numv1))
     622            0 :      ABI_MALLOC(new%qpts, (3, new%nqpt))
     623            0 :      ABI_MALLOC(new%pos_dpq, (3, new%mpert, new%nqpt))
     624            0 :      ABI_MALLOC(new%rhog1_g0, (2, new%numv1))
     625              :    end if
     626              : 
     627            0 :    call xmpi_bcast(new%cplex_v1, master, comm, ierr)
     628            0 :    call xmpi_bcast(new%ngfft3_v1, master, comm, ierr)
     629            0 :    call xmpi_bcast(new%iv_pinfoq, master, comm, ierr)
     630            0 :    call xmpi_bcast(new%qpts, master, comm, ierr)
     631            0 :    call xmpi_bcast(new%pos_dpq, master, comm, ierr)
     632            0 :    call xmpi_bcast(new%rhog1_g0, master, comm, ierr)
     633              :  end if
     634              : 
     635              :  ! Init crystal_t from the hdr read from file.
     636          116 :  new%cryst = new%hdr_ref%get_crystal()
     637          116 :  new%my_npert = new%natom3
     638              : 
     639              :  ! Init tables assuming no MPI distribution of perturbations.
     640          348 :  ABI_MALLOC(new%my_pinfo, (3, new%natom3))
     641          348 :  ABI_MALLOC(new%pert_table, (2, new%natom3))
     642          337 :  do iatom=1,new%natom
     643         1000 :    do idir=1,3
     644          663 :      pertcase = idir + (iatom-1) * 3
     645         2652 :      new%my_pinfo(:, pertcase) = [idir, iatom, pertcase]
     646         2210 :      new%pert_table(:, pertcase) = [xmpi_comm_self, pertcase]
     647              :    end do
     648              :  end do
     649              : 
     650              :  ! Init Born effective charges
     651         3221 :  ABI_CALLOC(new%zeff, (3, 3, new%natom))
     652         3105 :  ABI_CALLOC(new%zeff_raw, (3, 3, new%natom))
     653         9188 :  ABI_CALLOC(new%qstar, (3, 3, 3, new%natom))
     654              : 
     655              :  ! Internal MPI_type needed for calling fourdp!
     656          116 :  call initmpi_seq(new%mpi_enreg)
     657              : 
     658              :  ! Precompute symq_table for all q-points in the DVDB.
     659       313282 :  ABI_ICALLOC(new%symq_table, (4, 2, new%cryst%nsym, new%nqpt))
     660          798 :  do iq=1,new%nqpt
     661          682 :    if (mod(iq, nprocs) /= my_rank) cycle ! MPI parallelism
     662              :    call littlegroup_q(new%cryst%nsym, new%qpts(:,iq), new%symq_table(:,:,:,iq), &
     663          798 :      new%cryst%symrec, new%cryst%symafm, trev_q, prtvol=0)
     664              :  end do
     665          116 :  call xmpi_sum(new%symq_table, comm, ierr)
     666              : 
     667          116 :  call cwtime_report("- dvdb_init", cpu, wall, gflops)
     668          116 :  call timab(1800, 2, tsec)
     669              : 
     670          116 :  return
     671              : 
     672              :  ! Handle Fortran IO error
     673              : 10 continue
     674            0 :  ABI_ERROR(sjoin("Error while reading:", path, ch10, msg))
     675              : 
     676          464 : end subroutine dvdb_init
     677              : !!***
     678              : 
     679              : !----------------------------------------------------------------------
     680              : 
     681              : !!****f* m_dvdb/dvdb_open_read
     682              : !! NAME
     683              : !!  dvdb_open_read
     684              : !!
     685              : !! FUNCTION
     686              : !!  Open the file in read-only mode.
     687              : !!
     688              : !! INPUTS
     689              : !!   ngfft(18)=Info on the FFT mesh used for the DFPT potentials. Note that ngfft
     690              : !!     is the mesh used by the parent. In principle, it can differ from the one
     691              : !!     found in the file. In this case a Fourier interpolation is required.
     692              : !!   comm=MPI communicator
     693              : !!
     694              : !! SOURCE
     695              : 
     696           95 : subroutine dvdb_open_read(db, ngfft, comm)
     697              : 
     698              : !Arguments ------------------------------------
     699              : !scalars
     700              :  integer,intent(in) :: comm
     701              :  class(dvdb_t),intent(inout) :: db
     702              : !arrays
     703              :  integer,intent(in) :: ngfft(18)
     704              : 
     705              : !Local variables-------------------------------
     706              : !scalars
     707              :  integer :: nprocs, unt, ii
     708              :  character(len=500) :: msg
     709              : !arrays
     710              :  character(len=fnlen) :: pot_paths(3)
     711              : !************************************************************************
     712              : 
     713           95 :  if (db%rw_mode /= DVDB_NOMODE) then
     714            0 :    ABI_ERROR("DVDB should be in DVDB_NOMODE when open_read is called.")
     715              :  end if
     716           95 :  db%rw_mode = DVDB_READMODE
     717              : 
     718           95 :  nprocs = xmpi_comm_size(comm)
     719              : 
     720              :  ! Initialize tables to call fourdp in sequential
     721         1805 :  db%ngfft = ngfft
     722           95 :  call db%mpi_enreg%distribfft%init_seq('c', ngfft(2), ngfft(3), 'all')
     723           95 :  call db%mpi_enreg%distribfft%init_seq('f', ngfft(2), ngfft(3), 'all')
     724              : 
     725              :  ! Open the file.
     726          190 :  select case (db%iomode)
     727              :  case (IO_MODE_FORTRAN)
     728           95 :    if (open_file(db%path, msg, newunit=db%fh, form="unformatted", status="old", action="read") /= 0) then
     729            0 :      ABI_ERROR(msg)
     730              :    end if
     731           95 :    read(db%fh, err=10, iomsg=msg)
     732           95 :    read(db%fh, err=10, iomsg=msg)
     733           95 :    db%current_fpos = 1
     734              : 
     735              :  case (IO_MODE_MPI)
     736            0 :    ABI_ERROR("MPI not coded")
     737              : 
     738              :  case default
     739           95 :    ABI_ERROR(sjoin("Unsupported iomode:", itoa(db%iomode)))
     740              :  end select
     741              : 
     742              :  ! Read potentials induced by electric fields
     743              :  ! This requires ngfft so for the time being we call it here.
     744              :  ! I should try to add efield perturbations to DVDB but then I also have to handle symmetrization wrt idir!
     745           95 :  if (file_exists("__EFIELD_POTS__")) then
     746            0 :    call wrtout(std_out, " Reading Efield potentials from EFIELD_POTS")
     747            0 :    if (open_file("__EFIELD_POTS__", msg, newunit=unt, form="formatted") /= 0) then
     748            0 :      ABI_ERROR(msg)
     749              :    end if
     750            0 :    do ii=1,3
     751            0 :     read(unt, "(a)") pot_paths(ii)
     752              :    end do
     753            0 :    close(unt)
     754            0 :    call db%load_efield(pot_paths, comm)
     755              :  end if
     756              : 
     757           95 :  return
     758              : 
     759              :  ! Handle Fortran IO error
     760              : 10 continue
     761            0 :  ABI_ERROR(sjoin("Error while reading", db%path, ch10, msg))
     762              : 
     763              : end subroutine dvdb_open_read
     764              : !!***
     765              : 
     766              : !----------------------------------------------------------------------
     767              : 
     768              : !!****f* m_dvdb/dvdb_close
     769              : !! NAME
     770              : !!  dvdb_close
     771              : !!
     772              : !! FUNCTION
     773              : !! Close the file
     774              : !!
     775              : !! SOURCE
     776              : 
     777           95 : subroutine dvdb_close(db)
     778              : 
     779              : !Arguments ------------------------------------
     780              :  class(dvdb_t),intent(inout) :: db
     781              : !************************************************************************
     782              : 
     783          190 :  select case (db%iomode)
     784              :  case (IO_MODE_FORTRAN)
     785           95 :    close(db%fh)
     786              :  case default
     787           95 :    ABI_ERROR(sjoin("Unsupported iomode:", itoa(db%iomode)))
     788              :  end select
     789              : 
     790           95 :  db%rw_mode = DVDB_NOMODE
     791              : 
     792           95 : end subroutine dvdb_close
     793              : !!***
     794              : 
     795              : !----------------------------------------------------------------------
     796              : 
     797              : !!****f* m_dvdb/dvdb_free
     798              : !! NAME
     799              : !!  dvdb_free
     800              : !!
     801              : !! FUNCTION
     802              : !! Close the file and release the memory allocated.
     803              : !!
     804              : !! SOURCE
     805              : 
     806          235 : subroutine dvdb_free(db)
     807              : 
     808              : !Arguments ------------------------------------
     809              :  class(dvdb_t),target,intent(inout) :: db
     810              : 
     811              : !Local variables-------------------------------
     812          235 :  real(kind=sp), contiguous, pointer :: wsr_ptr(:,:,:,:,:)
     813              : !************************************************************************
     814              : 
     815              :  ! integer arrays
     816          116 :  ABI_SFREE(db%my_pinfo)
     817          235 :  ABI_SFREE(db%pert_table)
     818          235 :  ABI_SFREE(db%pos_dpq)
     819          235 :  ABI_SFREE(db%cplex_v1)
     820          235 :  ABI_SFREE(db%symq_table)
     821          235 :  ABI_SFREE(db%iv_pinfoq)
     822          235 :  ABI_SFREE(db%ngfft3_v1)
     823          235 :  ABI_SFREE(db%my_irpt2tot)
     824              : 
     825              :  ! real arrays
     826          235 :  ABI_SFREE(db%qpts)
     827          235 :  ABI_SFREE(db%my_rpt)
     828              : 
     829          235 :  ABI_SFREE(db%my_wratm)
     830          235 :  ABI_SFREE(db%rhog1_g0)
     831          235 :  ABI_SFREE(db%zeff)
     832          235 :  ABI_SFREE(db%zeff_raw)
     833          235 :  ABI_SFREE(db%qstar)
     834          235 :  ABI_SFREE(db%v1r_efield)
     835              : 
     836              :  ! Deallocate GPU arrays
     837          235 :  wsr_ptr => db%wsr
     838              : #ifdef HAVE_OPENMP_OFFLOAD
     839              :  !$OMP TARGET EXIT DATA MAP(delete:wsr_ptr) IF (db%gpu_option==ABI_GPU_OPENMP)
     840              : #endif
     841          235 :  ABI_SFREE(db%wsr)
     842              : 
     843              :  ! types
     844          235 :  call db%hdr_ref%free()
     845          235 :  call db%cryst%free()
     846          235 :  call destroy_mpi_enreg(db%mpi_enreg)
     847              : 
     848              :  ! Close the file but only if we have performed IO.
     849          235 :  if (db%rw_mode == DVDB_NOMODE) return
     850           95 :  call db%close()
     851              : 
     852          235 : end subroutine dvdb_free
     853              : !!***
     854              : 
     855              : !!****f* m_dvdb/dvdb_has_fields
     856              : !! NAME
     857              : !!  dvdb_has_fields
     858              : !!
     859              : !! FUNCTION
     860              : !!  Check whether the database stores first-order potentials (pot1) or first-order densities (den1)
     861              : !!
     862              : !! SOURCE
     863              : 
     864          182 : logical function dvdb_has_fields(db, choice, msg) result(ok)
     865              : 
     866              : !Arguments ------------------------------------
     867              :  class(dvdb_t),intent(in) :: db
     868              :  character(len=*),intent(in) :: choice
     869              :  character(len=*),intent(out) :: msg
     870              : !************************************************************************
     871              : 
     872              :  ! See m_hdr, more specifically all_abifiles for the correspondence between data and fform.
     873          182 :  msg = ""
     874          176 :  select case (choice)
     875              :  case ("pot1")
     876          176 :    ok = any(db%fform == pot1_fforms)
     877          176 :    if (.not. ok) msg = sjoin("expecting first order potentials with headform in", ltoa(pot1_fforms), "but got", itoa(db%fform))
     878              :  case ("den1")
     879            6 :    ok = any(db%fform == den1_fforms)
     880            6 :    if (.not. ok) msg = sjoin("expecting first order densities with headform in", ltoa(den1_fforms), "but got", itoa(db%fform))
     881              :  case default
     882          182 :    ABI_ERROR(sjoin("Invalid choice:", choice))
     883              :  end select
     884              : 
     885          182 : end function dvdb_has_fields
     886              : !!***
     887              : 
     888              : !----------------------------------------------------------------------
     889              : 
     890              : !!****f* m_dvdb/dvdb_print
     891              : !! NAME
     892              : !!  dvdb_print
     893              : !!
     894              : !! FUNCTION
     895              : !!  Print info on the object.
     896              : !!
     897              : !! INPUTS
     898              : !! units=Unit numbers for output.
     899              : !! header=Header string
     900              : !! prtvol=verbosity level
     901              : !!
     902              : !! SOURCE
     903              : 
     904          380 : subroutine dvdb_print(db, units, header, prtvol)
     905              : 
     906              : !Arguments ------------------------------------
     907              : !scalars
     908              :  class(dvdb_t),intent(in) :: db
     909              :  integer,intent(in) :: units(:), prtvol
     910              :  character(len=*),intent(in) :: header
     911              : 
     912              : !Local variables-------------------------------
     913              :  integer :: iv1,iq,idir,ipert,iatom
     914              :  character(len=5000) :: msg
     915              : ! *************************************************************************
     916              : 
     917          190 :  if (len_trim(header) == 0) then
     918           85 :    msg = ' ==== Info on the dvdb% object ==== '
     919              :  else
     920          105 :    msg = ' ==== '//trim(adjustl(header))//' ==== '
     921              :  end if
     922          190 :  call wrtout(units, msg)
     923              : 
     924          190 :  call wrtout(units, sjoin(" DVDB version:", itoa(db%version)))
     925          190 :  call wrtout(units, sjoin(" File path:", db%path))
     926          190 :  call wrtout(units, sjoin(" Number of v1scf potentials:", itoa(db%numv1)))
     927          190 :  call wrtout(units, sjoin(" Number of q-points in DVDB: ", itoa(db%nqpt)))
     928          190 :  call wrtout(units, sjoin("-P Number of CPUs for parallelism over perturbations:", itoa(db%nprocs_pert)))
     929          190 :  call wrtout(units, sjoin("-P Number of perturbations treated by this CPU:", itoa(db%my_npert)))
     930          190 :  call wrtout(units, sjoin(" Option for symmetrization of v1scf(r):", itoa(db%symv1)))
     931          190 :  call wrtout(units, " List of q-points: min(10, nqpt)")
     932         1238 :  do iq=1,min(db%nqpt, 10)
     933         1238 :    call wrtout(units, sjoin("[", itoa(iq),"]", ktoa(db%qpts(:,iq))))
     934              :  end do
     935          190 :  if (db%nqpt > 10) call wrtout(units, "...")
     936              : 
     937          190 :  call wrtout(units, sjoin(" Have dielectric tensor:", yesno(db%has_dielt)))
     938          190 :  call wrtout(units, sjoin(" Have Born effective charges:", yesno(db%has_zeff)))
     939          190 :  call wrtout(units, sjoin(" Have quadrupoles:", yesno(db%has_quadrupoles)))
     940          190 :  call wrtout(units, sjoin(" Have electric field:", yesno(db%has_efield)))
     941          190 :  call wrtout(units, sjoin(" Treatment of long-range part in V1scf (add_lr):", itoa(db%add_lr)))
     942          190 :  write(msg,"(a, f6.1)")" Damping factor for Gaussian filter (qdamp):", db%qdamp
     943          190 :  call wrtout(units, msg)
     944              : 
     945          190 :  if (db%has_dielt) then
     946           82 :    write(msg, '(a,3(a,3es16.6))') ' Dielectric tensor in Cart coords:', ch10, &
     947           82 :      db%dielt(1,1), db%dielt(1,2), db%dielt(1,3), ch10, &
     948           82 :      db%dielt(2,1), db%dielt(2,2), db%dielt(2,3), ch10, &
     949          164 :      db%dielt(3,1), db%dielt(3,2), db%dielt(3,3)
     950           82 :    call wrtout(units, msg)
     951              :  end if
     952              : 
     953          190 :  if (db%has_zeff) then
     954           82 :    call print_zeff(units, db%cryst, db%zeff, title=' Born effectives charges in Cart coords:')
     955              :    !call print_zeff(units, db%zeff_raw, db%cryst, title=' Born effectives charges before chneut: ')
     956              :  end if
     957              : 
     958          190 :  if (db%has_quadrupoles) then
     959            2 :    call wrtout(units, ' Dynamical Quadrupoles in Cartesian Coordinates:')
     960            6 :    do iatom=1,db%natom
     961           18 :      do idir=1,3
     962           12 :        write(msg,'(2(a,i0), 3(a,3es16.6))')' Q* for iatom: ', iatom, ' idir: ', idir,  ch10, &
     963           12 :          db%qstar(1,1,idir,iatom), db%qstar(1,2,idir,iatom), db%qstar(1,3,idir,iatom), ch10, &
     964           12 :          db%qstar(2,1,idir,iatom), db%qstar(2,2,idir,iatom), db%qstar(2,3,idir,iatom), ch10, &
     965           24 :          db%qstar(3,1,idir,iatom), db%qstar(3,2,idir,iatom), db%qstar(3,3,idir,iatom)
     966           16 :        call wrtout(units, msg)
     967              :      end do
     968              :    end do
     969              : 
     970            2 :    call wrtout(units, " Dynamical quadrupoles sum rule: \sum_\iatom Q_{beta,gamma}{iatom,idir} = 0 for nonpolar materials")
     971            8 :    do idir=1,3
     972            6 :      write(msg,'(a,i0,a,3(a,3es16.6))')" Sum rule for idir: ", idir, ch10, ch10, &
     973           42 :        sum(db%qstar(1,1,idir,:)), sum(db%qstar(1,2,idir,:)), sum(db%qstar(1,3,idir,:)), ch10, &
     974           42 :        sum(db%qstar(2,1,idir,:)), sum(db%qstar(2,2,idir,:)), sum(db%qstar(2,3,idir,:)), ch10, &
     975           48 :        sum(db%qstar(3,1,idir,:)), sum(db%qstar(3,2,idir,:)), sum(db%qstar(3,3,idir,:))
     976            8 :      call wrtout(units, msg)
     977              :    end do
     978              :  end if
     979              : 
     980          380 :  if (prtvol > 0) then
     981           43 :    call db%cryst%print(header="Crystal structure in DVDB file")
     982           43 :    call wrtout(units, "FFT mesh for potentials on file:")
     983           43 :    call wrtout(units, "q-point, idir, ipert, ngfft(:3)")
     984          517 :    do iv1=1,db%numv1
     985          474 :      idir = db%iv_pinfoq(1, iv1); ipert = db%iv_pinfoq(2, iv1); iq = db%iv_pinfoq(4, iv1)
     986          517 :      call wrtout(units, sjoin(ktoa(db%qpts(:,iq)), itoa(idir), itoa(ipert), ltoa(db%ngfft3_v1(:,iv1))))
     987              :    end do
     988              :  end if
     989              : 
     990              : contains
     991              : 
     992           82 : subroutine print_zeff(units, cryst, zeff, title)
     993              : 
     994              : !Arguments ------------------------------------
     995              : !scalars
     996              :  integer,intent(in) :: units(:)
     997              :  type(crystal_t),intent(in) :: cryst
     998              :  real(dp),intent(in) :: zeff(3,3,cryst%natom)
     999              :  character(len=*),optional,intent(in) :: title
    1000              : 
    1001              : !Local variables-------------------------------
    1002              :  integer :: iatom
    1003              :  character(len=5000) :: msg
    1004              : ! *************************************************************************
    1005              : 
    1006           82 :  if (present(title)) then
    1007           82 :    call wrtout(units, trim(title))
    1008              :  else
    1009            0 :    call wrtout(units, ' Born effectives charges in Cartesian coordinates: ')
    1010              :  end if
    1011              : 
    1012          246 :  do iatom=1,cryst%natom
    1013          164 :    write(msg, '(a,i0,1x,2a,3(a,3es16.6),a)')' iatom: ', iatom, ", type: ", cryst%symbol_iatom(iatom), ch10, &
    1014          164 :      zeff(1,1,iatom), zeff(1,2,iatom), zeff(1,3,iatom), ch10, &
    1015          164 :      zeff(2,1,iatom), zeff(2,2,iatom), zeff(2,3,iatom), ch10, &
    1016          328 :      zeff(3,1,iatom), zeff(3,2,iatom), zeff(3,3,iatom), ch10
    1017          246 :    call wrtout(units, msg)
    1018              :  end do
    1019              : 
    1020           82 :  write(msg,'(2a,3(a,3es16.6),a)')ch10,' Fulfillment of charge neutrality, \sum_{atom} Z^*_{ij,atom} = 0', ch10, &
    1021          738 :    sum(zeff(1,1,:)), sum(zeff(1,2,:)), sum(zeff(1,3,:)), ch10, &
    1022          738 :    sum(zeff(2,1,:)), sum(zeff(2,2,:)), sum(zeff(2,3,:)), ch10, &
    1023          820 :    sum(zeff(3,1,:)), sum(zeff(3,2,:)), sum(zeff(3,3,:)), ch10
    1024           82 :  call wrtout(units, msg)
    1025              : 
    1026           82 : end subroutine print_zeff
    1027              : 
    1028              : end subroutine dvdb_print
    1029              : !!***
    1030              : 
    1031              : !----------------------------------------------------------------------
    1032              : 
    1033              : !!****f* m_dvdb/dvdb_get_pinfo
    1034              : !! NAME
    1035              : !!  dvdb_get_pinfo
    1036              : !!
    1037              : !! FUNCTION
    1038              : !!  Return information on the perturbations available for a given q-point index.
    1039              : !!
    1040              : !! INPUTS
    1041              : !!  iqpt=Index of the q-point
    1042              : !!
    1043              : !! OUTPUT
    1044              : !!  nperts=Number of perturbations found.
    1045              : !!  cplex=2 if potentials are complex, 1 for real
    1046              : !!  pinfo(3,3*db%mpert)=Array with info on the perturbations present on file
    1047              : !!     pinfo(1, ip) gives the `idir` index of the ip-th perturbation.
    1048              : !!     pinfo(2, ip) gives the `ipert` index of the ip-th perturbation.
    1049              : !!     pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3
    1050              : !!
    1051              : !! SOURCE
    1052              : 
    1053         1718 : integer function dvdb_get_pinfo(db, iqpt, cplex, pinfo) result(nperts)
    1054              : 
    1055              : !Arguments ------------------------------------
    1056              : !scalars
    1057              :  type(dvdb_t),intent(in) :: db
    1058              :  integer,intent(in) :: iqpt
    1059              :  integer,intent(out) :: cplex
    1060              : !arrays
    1061              :  integer,intent(out) :: pinfo(3,3*db%mpert)
    1062              : 
    1063              : !Local variables-------------------------------
    1064              : !scalars
    1065              :  integer :: idir,ipert,iv1
    1066              : ! *************************************************************************
    1067              : 
    1068              :  ! Get the number of perturbations computed for this iqpt
    1069       165374 :  pinfo = 0; cplex = 0; nperts = 0
    1070         5048 :  do ipert=1,db%natom ! selects atomic perturbations only.
    1071        15038 :     do idir=1,3
    1072         9990 :       iv1 = db%pos_dpq(idir,ipert,iqpt)
    1073        13320 :       if (iv1 /= 0) then
    1074         5416 :         nperts = nperts + 1
    1075        21664 :         pinfo(:, nperts) = [idir, ipert, idir + (ipert-1)*3]
    1076         5416 :         if (cplex == 0) cplex = db%cplex_v1(iv1)
    1077         5416 :         ABI_CHECK_IEQ(cplex, db%cplex_v1(iv1), "cplex should be constant for given q!")
    1078              :       end if
    1079              :     end do
    1080              :  end do
    1081              : 
    1082         1718 : end function dvdb_get_pinfo
    1083              : !!***
    1084              : 
    1085              : !----------------------------------------------------------------------
    1086              : 
    1087              : !!****f* m_dvdb/dvdb_read_onev1
    1088              : !! NAME
    1089              : !!  dvdb_read_onev1
    1090              : !!
    1091              : !! FUNCTION
    1092              : !!  Read the DFPT potential for the specified (idir, ipert, iqpt).
    1093              : !!  Note that iqpt is the index in dvdb%qpts. Use dvdb_findq to
    1094              : !!  get the index from the q-point in reduced coordinates.
    1095              : !!
    1096              : !! INPUTS
    1097              : !!  idir=Direction of the perturbation
    1098              : !!  ipert=Perturbation type.
    1099              : !!  iqpt=Index of the q-point in dvdb%qpts
    1100              : !!  cplex=1 if real, 2 if complex potentials.
    1101              : !!  nfft=Number of fft-points treated by this processors
    1102              : !!  ngfft(18)=contain all needed information about 3D FFT.
    1103              : !!
    1104              : !! OUTPUT
    1105              : !!  ierr=Non-zero if error.
    1106              : !!  v1scf(cplex*nfft, nspden)=DFT potential associated to (idir, ipert, iqpt).
    1107              : !!  msg=String with error message if ierr /= 0.
    1108              : !!
    1109              : !! SOURCE
    1110              : 
    1111         5360 : integer function dvdb_read_onev1(db, idir, ipert, iqpt, cplex, nfft, ngfft, v1scf, msg) result(ierr)
    1112              : 
    1113              : !Arguments ------------------------------------
    1114              : !scalars
    1115              :  integer,intent(in) :: idir,ipert,iqpt,cplex,nfft
    1116              :  character(len=*),intent(out) :: msg
    1117              :  class(dvdb_t),intent(inout) :: db
    1118              : !arrays
    1119              :  integer,intent(in) :: ngfft(18)
    1120              :  real(dp),intent(out) :: v1scf(cplex*nfft,db%nspden)
    1121              : 
    1122              : !Local variables-------------------------------
    1123              : !scalars
    1124              :  integer,save :: enough = 0
    1125              :  integer :: iv1,ispden,nfftot_file,nfftot_out,ifft
    1126              : !arrays
    1127              :  integer :: ngfft_in(18),ngfft_out(18)
    1128         5360 :  real(dp),allocatable :: v1r_file(:,:)
    1129              : ! *************************************************************************
    1130              : 
    1131              :  ! Consistency checks
    1132         5360 :  ierr = 1
    1133         5360 :  iv1 = db%pos_dpq(idir,ipert,iqpt)
    1134              : 
    1135         5360 :  if (iv1 == 0) then
    1136            0 :    write(msg,"(3(a,i0))")"Cannot find idir: ",idir,", ipert: ",ipert,", iqpt:",iqpt
    1137            0 :    return
    1138              :  end if
    1139              : 
    1140         5360 :  if (cplex /= db%cplex_v1(iv1)) then
    1141            0 :    write(msg,"(2(a,i0))")"Wrong cplex. Expecting: ",db%cplex_v1(iv1),", received: ",cplex
    1142            0 :    return
    1143              :  end if
    1144              : 
    1145              :  ! Find (idir, ipert, iqpt) and skip the header.
    1146         5360 :  call dvdb_seek(db, idir, ipert, iqpt)
    1147         5360 :  ierr = my_hdr_skip(db%fh, idir, ipert, db%qpts(:,iqpt), msg)
    1148         5360 :  if (ierr /= 0) then
    1149            0 :    msg = sjoin("In my_hdr_skip:", msg)
    1150            0 :    return
    1151              :  end if
    1152              : 
    1153              :  ! Read v1 from file.
    1154        21440 :  nfftot_out = product(ngfft(:3)); nfftot_file = product(db%ngfft3_v1(:3, iv1))
    1155              : 
    1156        16244 :  if (all(ngfft(:3) == db%ngfft3_v1(:3, iv1))) then
    1157         7256 :    do ispden=1,db%nspden
    1158         7256 :      read(db%fh, err=10, iomsg=msg) (v1scf(ifft, ispden), ifft=1,cplex*nfftot_file)
    1159              :    end do
    1160              :  else
    1161              :    ! The FFT mesh used in the caller differ from the one found in the DVDB --> Fourier interpolation
    1162         1732 :    if (enough == 0) ABI_COMMENT("Performing FFT interpolation of DFPT potentials as input ngfft differs from ngfft_file.")
    1163         1732 :    enough = enough + 1
    1164         6928 :    ABI_MALLOC(v1r_file, (cplex*nfftot_file, db%nspden))
    1165         3464 :    do ispden=1,db%nspden
    1166         3464 :      read(db%fh, err=10, iomsg=msg) (v1r_file(ifft, ispden), ifft=1,cplex*nfftot_file)
    1167              :    end do
    1168              : 
    1169              :    ! Call fourier_interpol_seq to get v1scf on the ngfft mesh.
    1170         1732 :    ngfft_in = ngfft; ngfft_out = ngfft
    1171        12124 :    ngfft_in(1:3) = db%ngfft3_v1(1:3, iv1); ngfft_out(1:3) = ngfft(1:3)
    1172        12124 :    ngfft_in(4:6) = ngfft_in(1:3); ngfft_out(4:6) = ngfft_out(1:3)
    1173        36372 :    ngfft_in(9:18) = 0; ngfft_out(9:18) = 0
    1174         1732 :    ngfft_in(10) = 1; ngfft_out(10) = 1
    1175              : 
    1176         1732 :    call fourier_interpol_seq(cplex, db%nspden, nfftot_file, ngfft_in, nfft, ngfft, v1r_file, v1scf)
    1177         1732 :    ABI_FREE(v1r_file)
    1178              :  end if
    1179              : 
    1180              :  ! Skip record with rhog1_g0 (if present)
    1181         5360 :  if (db%version > 1) read(db%fh, err=10, iomsg=msg)
    1182              : 
    1183         5360 :  db%current_fpos = db%current_fpos + 1
    1184              :  !write(std_out, *)"incr current_fpos", db%current_fpos
    1185              : 
    1186         5360 :  return
    1187              : 
    1188              :  ! Handle Fortran IO error
    1189              : 10 continue
    1190            0 :  ierr = 1
    1191            0 :  msg = sjoin("Error while reading", db%path, ch10, msg)
    1192              : 
    1193        10720 : end function dvdb_read_onev1
    1194              : !!***
    1195              : 
    1196              : !----------------------------------------------------------------------
    1197              : 
    1198              : !!****f* m_dvdb/dvdb_readsym_allv1
    1199              : !! NAME
    1200              : !!  dvdb_readsym_allv1
    1201              : !!
    1202              : !! FUNCTION
    1203              : !!  Read all 3*natom DFPT potentials for the given iqpt (only atomic perturbations).
    1204              : !!
    1205              : !!  The routine will:
    1206              : !!
    1207              : !!     1) Reconstruct the potentials by symmetry if the DVDB contains less than 3*natom potentials.
    1208              : !!     2) interpolate the data if the input FFT mesh defined by `ngfft` differs
    1209              : !!        from the one used to store data in the file.
    1210              : !!
    1211              : !!  Note that iqpt is the index in dvdb%qpts. Use dvdb_findq to
    1212              : !!  get the index from the q-point in reduced coordinates.
    1213              : !!
    1214              : !! INPUTS
    1215              : !!  iqpt=Index of the q-point in dvdb%qpts
    1216              : !!  nfft=Number of fft-points treated by this processors
    1217              : !!  ngfft(18)=contain all needed information about 3D FFT
    1218              : !!  comm=MPI communicator
    1219              : !!
    1220              : !! OUTPUT
    1221              : !!  cplex=1 if real, 2 if complex.
    1222              : !!  v1scf(cplex, nfft, nspden, 3*natom)= v1scf potentials on the real-space FFT mesh for the 3*natom perturbations.
    1223              : !!
    1224              : !! SOURCE
    1225              : 
    1226         1660 : subroutine dvdb_readsym_allv1(db, iqpt, cplex, nfft, ngfft, v1scf, comm)
    1227              : 
    1228              : !Arguments ------------------------------------
    1229              : !scalars
    1230              :  integer,intent(in) :: iqpt,nfft,comm
    1231              :  integer,intent(out) :: cplex
    1232              :  class(dvdb_t),intent(inout) :: db
    1233              : !arrays
    1234              :  integer,intent(in) :: ngfft(18)
    1235              :  real(dp) ABI_ASYNC ,allocatable,intent(out) :: v1scf(:,:,:,:)
    1236              : 
    1237              : !Local variables-------------------------------
    1238              : !scalars
    1239              :  integer,parameter :: master=0
    1240              :  integer :: ipc,npc,idir,ipert,pcase,my_rank,nproc,ierr,mu
    1241              :  character(len=500) :: msg
    1242              : !arrays
    1243         1660 :  integer :: pinfo(3,3*db%mpert),pflag(3, db%natom)
    1244              :  real(dp) :: tsec(2)
    1245         1660 :  integer,allocatable :: requests(:)
    1246              : ! *************************************************************************
    1247              : 
    1248              :  ! Keep track of total time spent.
    1249         1660 :  call timab(1805, 1, tsec)
    1250              : 
    1251         1660 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
    1252              : 
    1253              :  ! Get number of perturbations computed for this iqpt as well as cplex.
    1254         1660 :  npc = dvdb_get_pinfo(db, iqpt, cplex, pinfo)
    1255         1660 :  ABI_CHECK(npc /= 0, "npc == 0!")
    1256              : 
    1257         9960 :  ABI_MALLOC_OR_DIE(v1scf, (cplex, nfft, db%nspden, 3*db%natom), ierr)
    1258              : 
    1259              :  ! Master read all available perturbations and broadcasts data (non-blocking to overlap IO and MPI)
    1260         4980 :  ABI_MALLOC(requests, (npc))
    1261              : 
    1262         6964 :  do ipc=1,npc
    1263         5304 :    idir = pinfo(1,ipc); ipert = pinfo(2,ipc); pcase = pinfo(3, ipc)
    1264         5304 :    if (my_rank == master) then
    1265         5304 :      if (db%read_onev1(idir, ipert, iqpt, cplex, nfft, ngfft, v1scf(:,:,:,pcase), msg) /= 0) then
    1266            0 :        ABI_ERROR(msg)
    1267              :      end if
    1268              :    end if
    1269         6964 :    if (nproc > 1) call xmpi_ibcast(v1scf(:,:,:,pcase), master, comm, requests(ipc), ierr)
    1270              :  end do
    1271              : 
    1272         1660 :  if (nproc > 1) call xmpi_waitall(requests, ierr)
    1273         1660 :  ABI_FREE(requests)
    1274              : 
    1275              :  ! Return if all perts are available.
    1276         1660 :  if (npc == 3*db%natom) then
    1277          380 :    if (db%symv1==1) then
    1278           16 :      if (db%debug) write(std_out,*)"Potentials are available but will call v1phq_symmetrize because of symv1"
    1279          112 :      do mu=1,db%natom3
    1280              :        !if (mod(mu, nproc) /= my_rank) cycle ! MPI parallelism.
    1281           96 :        idir = mod(mu-1, 3) + 1; ipert = (mu - idir) / 3 + 1
    1282              :        call v1phq_symmetrize(db%cryst,idir,ipert,db%symq_table(:,:,:,iqpt),ngfft,cplex,nfft,&
    1283          112 :          db%nspden,db%nsppol,db%mpi_enreg,v1scf(:,:,:,mu))
    1284              :        !call MPI_Ibcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, MPI_Request *request)
    1285              :      end do
    1286              :    end if
    1287          380 :    if (db%debug) write(std_out,*)"All perts available. Returning"
    1288          380 :    call timab(1805, 2, tsec)
    1289              :    return
    1290              :  end if
    1291              : 
    1292              :  ! Perturbation are missing and we have to reconstruct them by symmetry.
    1293              :  ! This is the common case when DFPT calculations are done for independent perturbations only.
    1294         1280 :  if (db%debug) write(std_out,*)sjoin("Will use symmetries to recostruct:", itoa(3*db%natom - npc), "perturbations")
    1295              : 
    1296              :  ! 0 if pert is not available.
    1297              :  ! 1 if pert is on file.
    1298              :  ! 2 if pert has been reconstructed by symmetry.
    1299        11240 :  pflag = 0
    1300         4364 :  do ipc=1,npc
    1301         4364 :    pflag(pinfo(1,ipc), pinfo(2,ipc)) = 1
    1302              :  end do
    1303              : 
    1304         1280 :  call v1phq_complete(db%cryst,db%qpts(:,iqpt),ngfft,cplex,nfft,db%nspden,db%nsppol,db%mpi_enreg,db%symv1,pflag,v1scf)
    1305              : 
    1306         1280 :  call timab(1805, 2, tsec)
    1307              : 
    1308              : end subroutine dvdb_readsym_allv1
    1309              : !!***
    1310              : 
    1311              : !----------------------------------------------------------------------
    1312              : 
    1313              : !!****f* m_dvdb/dvdb_readsym_qbz
    1314              : !! NAME
    1315              : !!  dvdb_readsym_qbz
    1316              : !!
    1317              : !! FUNCTION
    1318              : !! This is the MAIN ENTRY POINT for client code.
    1319              : !! Reconstruct the DFPT potential for a q-point in the BZ starting
    1320              : !! from its symmetrical image in the IBZ.
    1321              : !!
    1322              : !! INPUTS
    1323              : !!  cryst<crystal_t>=crystal structure parameters
    1324              : !!  qbz(3)=Q-point in BZ.
    1325              : !!  qbz2db(6)=Symmetry mapping qbz --> DVDB qpoints produced using the SYMREC convention.
    1326              : !!    Note that qbz2db(1) should give the index in the set of q-points in the DVDB
    1327              : !!    that is not necessarily ORDERED as the IBZ computed by the Abinit routines.
    1328              : !!  nfft=Number of fft-points treated by this processors
    1329              : !!  ngfft(18)=contain all needed information about 3D FFT
    1330              : !!  comm=MPI communicator (either xmpi_comm_self or comm for perturbations.
    1331              : !!
    1332              : !! OUTPUT
    1333              : !!  cplex=1 if real, 2 if complex.
    1334              : !!  v1scf(cplex, nfft, nspden, db%my_npert)= v1scf potentials on the real-space FFT mesh
    1335              : !!   for the db%my_npert perturbations treated by this MPI rank.
    1336              : !!
    1337              : !! SOURCE
    1338              : 
    1339         1285 : subroutine dvdb_readsym_qbz(db, cryst, qbz, qbz2db, cplex, nfft, ngfft, v1scf, comm)
    1340              : 
    1341              : !Arguments ------------------------------------
    1342              : !scalars
    1343              :  class(dvdb_t),intent(inout) :: db
    1344              :  integer,intent(in) :: nfft,comm
    1345              :  integer,intent(out) :: cplex
    1346              :  type(crystal_t),intent(in) :: cryst
    1347              : !arrays
    1348              :  real(dp),intent(in) :: qbz(3)
    1349              :  integer,intent(in) :: ngfft(18), qbz2db(6)
    1350              :  real(dp),allocatable,intent(out) :: v1scf(:,:,:,:)
    1351              : 
    1352              : !Local variables-------------------------------
    1353              : !scalars
    1354              :  integer :: db_iqpt, itimrev, isym, imyp
    1355              :  logical :: isirr_q
    1356              : !arrays
    1357              :  integer :: g0q(3)
    1358              :  real(dp) :: tsec(2)
    1359         1285 :  real(dp) ABI_ASYNC, allocatable :: work(:,:,:,:), work2(:,:,:,:)
    1360              : ! *************************************************************************
    1361              : 
    1362              :  ABI_UNUSED(qbz(1))
    1363              : 
    1364              :  ! Keep track of total time spent.
    1365         1285 :  call timab(1802, 1, tsec)
    1366              : 
    1367         1285 :  db_iqpt = qbz2db(1)
    1368              : 
    1369              :  ! IS(q_dvdb) + g0q = q_bz
    1370         5140 :  isym = qbz2db(2); itimrev = qbz2db(6) + 1; g0q = qbz2db(3:5)
    1371         4731 :  isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0))
    1372              : 
    1373              :  ! Read the dvscf potentials in the IBZ for all 3*natom perturbations.
    1374              :  ! This call allocates v1scf(cplex, nfftf, nspden, 3*natom)
    1375         1285 :  call db%readsym_allv1(db_iqpt, cplex, nfft, ngfft, v1scf, comm)
    1376              : 
    1377         1285 :  if (.not. isirr_q) then
    1378              :    ! Must rotate db_iqpt to get potential for qpoint in the BZ.
    1379              :    ! Be careful with the shape of output v1scf because the routine returns db%my_npert potentials.
    1380              : 
    1381          702 :    if (db%my_npert == db%natom3) then
    1382         4212 :      ABI_MALLOC(work, (cplex, nfft, db%nspden, db%natom3))
    1383    154012518 :      work = v1scf
    1384              :      call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, &
    1385          702 :                        db%nspden, db%mpi_enreg, work, v1scf, db%comm_pert)
    1386          702 :      ABI_FREE(work)
    1387              : 
    1388              :    else
    1389              :      ! Parallelism over perturbations.
    1390            0 :      ABI_MALLOC(work2, (cplex, nfft, db%nspden, db%natom3))
    1391              : 
    1392              :      ! All 3 natom have been read in v1scf by dvdb_readsym_allv1
    1393              :      call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, &
    1394            0 :                          db%nspden, db%mpi_enreg, v1scf, work2, db%comm_pert)
    1395              : 
    1396              :      ! Reallocate v1scf with my_npert and extract data from work2.
    1397            0 :      ABI_REMALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert))
    1398            0 :      do imyp=1,db%my_npert
    1399            0 :        v1scf(:,:,:,imyp) = work2(:,:,:,db%my_pinfo(3, imyp))
    1400              :      end do
    1401            0 :      ABI_FREE(work2)
    1402              :    end if
    1403              : 
    1404              :  else
    1405              :    ! Handle potentials read from file in case of parallelism over perturbations.
    1406          583 :    if (db%my_npert /= db%natom3) then
    1407            0 :      ABI_MALLOC(work, (cplex, nfft, db%nspden, db%my_npert))
    1408            0 :      do imyp=1,db%my_npert
    1409            0 :        work(:,:,:,imyp) = v1scf(:,:,:,db%my_pinfo(3, imyp))
    1410              :      end do
    1411              : 
    1412            0 :      ABI_REMALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert))
    1413            0 :      v1scf = work
    1414            0 :      ABI_FREE(work)
    1415              :    end if
    1416              :  end if ! not isirr_q
    1417              : 
    1418         1285 :  call timab(1802, 2, tsec)
    1419              : 
    1420         1285 : end subroutine dvdb_readsym_qbz
    1421              : !!***
    1422              : 
    1423              : !----------------------------------------------------------------------
    1424              : 
    1425              : !!****f* m_dvdb/dvdb_read_vxc1_qbz
    1426              : !! NAME
    1427              : !!  dvdb_read_vxc1_qbz
    1428              : !!
    1429              : !! FUNCTION
    1430              : !! Compute the first-order change of the exchange-correlation potential
    1431              : !! for a q-point in the BZ starting from its symmetrical image in the IBZ.
    1432              : !!
    1433              : !! INPUTS
    1434              : !!  cryst<crystal_t>=crystal structure parameters
    1435              : !!  dtset<dataset_type>=All input variables for this dataset
    1436              : !!  qbz(3)=Q-point in BZ.
    1437              : !!  mapc_qq2dvdb(6)=Symmetry mapping qbz, see m_kpts.f for a description
    1438              : !!  nfft=Number of fft-points treated by this processors
    1439              : !!  ngfft(18)=contain all needed information about 3D FFT
    1440              : !!  nkxc=second dimension of the array kxc, see rhohxc.f for a description
    1441              : !!  kxc(nfftf,nkxc)=second derivative of the exchange-correlation functional
    1442              : !!  non_magnetic_xc=true if density/potential is handled as non-magnetic
    1443              : !!  usexcnhat=0, the exchange-correlation potential does not include the compensation charge density
    1444              : !!  comm=MPI communicator (either xmpi_comm_self or comm for perturbations
    1445              : !!
    1446              : !! OUTPUT
    1447              : !!  drho_cplex=1 if real, 2 if complex.
    1448              : !!  vxc1(drho_cplex, nfft, nspden, db%my_npert)= vxc1 potentials on the real-space FFT mesh
    1449              : !!  for the db%my_npert perturbations treated by this MPI rank.
    1450              : !!
    1451              : !! SOURCE
    1452              : 
    1453           80 : subroutine dvdb_read_vxc1_qbz(db, dtset, cryst, qbz, mapc_qq2dvdb, drho_cplex, nfft, ngfft, nkxc, kxc, &
    1454              :                               vxc1, non_magnetic_xc, usexcnhat, comm)
    1455              : 
    1456              : !Arguments ------------------------------------
    1457              : !scalars
    1458              :  class(dvdb_t),intent(inout) :: db
    1459              :  integer,intent(in) :: nfft, nkxc, usexcnhat, comm
    1460              :  integer,intent(out) :: drho_cplex
    1461              :  real(dp),intent(in) :: qbz(3)
    1462              :  type(dataset_type),intent(in) :: dtset
    1463              :  type(crystal_t),intent(in) :: cryst
    1464              :  logical,intent(in) :: non_magnetic_xc
    1465              : !arrays
    1466              :  integer,intent(in) :: ngfft(18), mapc_qq2dvdb(6)
    1467              :  real(dp),intent(in) :: kxc(nfft,nkxc)
    1468              :  real(dp),allocatable,intent(out) :: vxc1(:,:,:,:)
    1469              : 
    1470              : !Local variables-------------------------------
    1471              : !scalars
    1472              :  integer :: option,imyp
    1473              : !arrays
    1474           80 :  real(dp),allocatable :: rho1(:,:,:,:)
    1475              :  real(dp) :: dum_nhat(0), dum_xccc3d1(0)
    1476              : ! *************************************************************************
    1477              : 
    1478              :  ! Get rho1(cplex, nfftf, nspden, my_npert))
    1479           80 :  call db%readsym_qbz(cryst, qbz, mapc_qq2dvdb, drho_cplex, nfft, ngfft, rho1, comm)
    1480              : 
    1481           80 :  option=2 ! if 2, treat only density change
    1482          480 :  ABI_MALLOC(vxc1, (drho_cplex, nfft, dtset%nspden, db%my_npert))
    1483          560 :  do imyp=1,db%my_npert
    1484              :    call dfpt_mkvxc(drho_cplex,dtset%ixc,kxc,db%mpi_enreg,nfft,ngfft,dum_nhat,0,dum_nhat,0,&
    1485              :                    nkxc,non_magnetic_xc,dtset%nspden,0,option,qbz,rho1(:,:,:,imyp), &
    1486          560 :                    cryst%rprimd,usexcnhat,vxc1(:,:,:,imyp),dum_xccc3d1)
    1487              :  end do
    1488           80 :  ABI_FREE(rho1)
    1489              : 
    1490           80 :   end subroutine dvdb_read_vxc1_qbz
    1491              : !!***
    1492              : 
    1493              : !----------------------------------------------------------------------
    1494              : 
    1495              : !!****f* m_dvdb/v1phq_complete
    1496              : !! NAME
    1497              : !! v1phq_complete
    1498              : !!
    1499              : !! FUNCTION
    1500              : !!  Use the symmetries of the little group of the q-point to reconstruct
    1501              : !!  the first order potentials starting from an initial irreducible set.
    1502              : !!
    1503              : !! INPUTS
    1504              : !!  cryst<crystal_t>=crystal structure parameters
    1505              : !!  qpt(3)=q-point in reduced coordinates.
    1506              : !!  ngfft(18)=Info of FFT grid.
    1507              : !!  cplex=1 if real potentials (qpt==gamma), 2 if complex
    1508              : !!  nfft=(effective) number of FFT grid points (for this proc).
    1509              : !!  nspden=number of spin-density components
    1510              : !!  nsppol=Number of independent spin polarizations
    1511              : !!  mpi_enreg=information about MPI parallelization
    1512              : !!  symv1=If 1, the new potentials are symmetrized using the set of symmetries that leaves the
    1513              : !!    perturbation invariant.
    1514              : !!
    1515              : !! SIDE EFFECTS
    1516              : !!  pflag(3,natom)= For each atomic perturbation:
    1517              : !!     0 if pert is not available. 1 if pert is available. 2 if pert has been reconstructed by symmetry.
    1518              : !!     Initialized by the caller. Changed in output.
    1519              : !!  v1scf(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials.
    1520              : !!    in input: filled with the irreducible potentials (corresponding pflag set to 1)
    1521              : !!    output: Contains full set of perturbations.
    1522              : !!
    1523              : !! SOURCE
    1524              : 
    1525         1280 : subroutine v1phq_complete(cryst,qpt,ngfft,cplex,nfft,nspden,nsppol,mpi_enreg,symv1,pflag,v1scf)
    1526              : 
    1527              : !Arguments ------------------------------------
    1528              : !scalars
    1529              :  integer,intent(in) :: cplex,nfft,nspden,nsppol
    1530              :  integer,intent(in) :: symv1
    1531              :  type(crystal_t),intent(in) :: cryst
    1532              :  type(MPI_type),intent(in) :: mpi_enreg
    1533              : !arrays
    1534              :  integer,intent(in) :: ngfft(18)
    1535              :  integer,intent(inout) :: pflag(3, cryst%natom)
    1536              :  real(dp),intent(in) :: qpt(3)
    1537              :  real(dp),intent(inout) :: v1scf(cplex*nfft,nspden,3*cryst%natom)
    1538              : 
    1539              : !Local variables-------------------------------
    1540              : !scalars
    1541              :  integer,parameter :: syuse0=0,rfmeth2=2,tim_fourdp0=0
    1542              :  integer :: idir,ipert,tsign,isym_eq,itirev_eq,ipert_eq !,itirev
    1543              :  integer :: pcase,trev_q,idir_eq,pcase_eq,ispden,cnt
    1544              :  integer :: i1,i2,i3,id1,id2,id3,n1,n2,n3,ind1,ind2,j1,j2,j3,l1,l2,l3,k1,k2,k3,nfftot
    1545              :  real(dp) :: arg
    1546              :  logical :: has_phase
    1547              :  logical,parameter :: debug=.False.
    1548              :  character(len=500) :: msg
    1549              :  !integer,save :: enough=0
    1550              : !arrays
    1551              :  integer :: symrel_eq(3,3),symrec_eq(3,3),g0_qpt(3),l0(3),tsm1g(3) !symm(3,3),
    1552         2560 :  integer :: symq(4,2,cryst%nsym)
    1553              :  real(dp) :: phnon1(2),tnon(3)
    1554         1280 :  real(dp),allocatable :: workg(:,:), workg_eq(:,:),v1g(:,:,:)
    1555              : ! *************************************************************************
    1556              : 
    1557         5120 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3))
    1558         1280 :  ABI_CHECK(nfftot == nfft, "FFT parallelism not supported")
    1559         1280 :  id1 = n1/2+2; id2 = n2/2+2; id3 = n3/2+2
    1560              : 
    1561         5120 :  ABI_MALLOC(v1g, (2,nfft,nspden))
    1562         3840 :  ABI_MALLOC(workg_eq, (2, nfft))
    1563         2560 :  ABI_MALLOC(workg, (2, nfft))
    1564              : 
    1565              :  ! Examine the symmetries of the q wavevector
    1566         1280 :  call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,trev_q,prtvol=0)
    1567              : 
    1568              : pcase_loop: &
    1569         8750 :  do pcase=1,3*cryst%natom
    1570         7470 :    idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1
    1571         7470 :    if (pflag(idir, ipert) /= 0) cycle ! This pcase is available
    1572              : 
    1573              :    ! Find symmetry which links to the perturbation requested (pcase)
    1574         4386 :    call find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0=.true.)
    1575              :    !if (isym_eq == -1) then
    1576              :    !  call find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0=.true.)
    1577              :    !end if
    1578              : 
    1579         4386 :    if (isym_eq == -1) then
    1580              :      if (debug) write(std_out,*)"Cannot find isym eq for idir, ipert:", idir,ipert
    1581              :      cycle pcase_loop
    1582              :    end if
    1583              : 
    1584              :    ! set flag since we will reconstruct pcase from isym_eq.
    1585         4386 :    pflag(idir, ipert) = 2
    1586              : 
    1587        57018 :    symrel_eq = cryst%symrel(:,:,isym_eq)
    1588        57018 :    symrec_eq = cryst%symrec(:,:,isym_eq)
    1589         4386 :    tsign = 3-2*itirev_eq
    1590              : 
    1591              :    ! Phase due to L0 + R^{-1}tau
    1592        17544 :    l0 = cryst%indsym(1:3,isym_eq,ipert)
    1593              : 
    1594       122808 :    tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym_eq))
    1595        10615 :    has_phase = any(abs(tnon) > tol12)
    1596              :    ! FIXME
    1597              :    !ABI_CHECK(.not. has_phase, "has phase must be tested")
    1598              :    !if (has_phase) then
    1599              :    !  enough = enough + 1
    1600              :    !  if (enough == 1) ABI_WARNING("has phase must be tested")
    1601              :    !end if
    1602              : 
    1603    156331938 :    workg = zero
    1604              : 
    1605              :    ! Reconstruct DFPT potential. Final results stored in v1g.
    1606              :    if (debug) write(std_out,*)"Reconstructing idir:", idir, ", ipert:", ipert
    1607    156336324 :    v1g = zero; cnt = 0
    1608        17544 :    do idir_eq=1,3
    1609        13158 :      if (symrec_eq(idir, idir_eq) == 0) cycle
    1610         5792 :      cnt = cnt + 1
    1611         5792 :      pcase_eq = idir_eq + (ipert_eq-1)*3
    1612              :      if (debug) write(std_out,*) "idir_eq: ", idir_eq, ", ipert_eq: ", ipert_eq, ", tsign: ", tsign
    1613              : 
    1614         5792 :      if (pflag(idir_eq, ipert_eq) == 0) then
    1615            0 :        write(msg, *)"pflag for idir_eq, ipert_eq", idir_eq, ipert_eq, "cannot be zero"
    1616            0 :        ABI_ERROR(msg)
    1617              :      end if
    1618              : 
    1619              :      !if (pflag(idir_eq, ipert_eq) == 0) then
    1620              :      !  write(msg, *)"pflag for idir_eq, ipert_eq", idir_eq, ipert_eq, "cannot be zero"
    1621              :      !  ABI_ERROR(msg)
    1622              :      !end if
    1623              : 
    1624        15970 :      do ispden=1,nspden
    1625              :        ! Get symmetric perturbation in G-space in workg_eq array.
    1626         5792 :        call fourdp(cplex,workg_eq,v1scf(:,ispden,pcase_eq),-1,mpi_enreg,nfft,1,ngfft,tim_fourdp0)
    1627              :        !call zerosym(workg_eq,cplex,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
    1628              : 
    1629              :        !call rotate_fqg(itirev_eq,symrec_eq,qpt,tnon,ngfft,nfft,nspden,workg_eq,workg)
    1630         5792 :        ind1=0
    1631       125902 :        do i3=1,n3
    1632              :          ! Get location of G vector (grid point) centered at 0 0 0
    1633       120110 :          l3 = i3-(i3/id3)*n3-1
    1634      2853400 :          do i2=1,n2
    1635      2727498 :            l2 = i2-(i2/id2)*n2-1
    1636     71026750 :            do i1=1,n1
    1637     68179142 :              ind1=ind1+1
    1638              : 
    1639     68179142 :              l1 = i1-(i1/id1)*n1-1
    1640              : 
    1641              :              ! Get rotated G vector Gj for each symmetry element
    1642              :              ! -- here we use the TRANSPOSE of symrel_eq; assuming symrel_eq expresses
    1643              :              ! the rotation in real space, the transpose is then appropriate
    1644              :              ! for G space symmetrization (p. 1172d,e of notes, 2 June 1995).
    1645     68179142 :              j1 = tsign * (symrel_eq(1,1)*l1+symrel_eq(2,1)*l2+symrel_eq(3,1)*l3)
    1646     68179142 :              j2 = tsign * (symrel_eq(1,2)*l1+symrel_eq(2,2)*l2+symrel_eq(3,2)*l3)
    1647     68179142 :              j3 = tsign * (symrel_eq(1,3)*l1+symrel_eq(2,3)*l2+symrel_eq(3,3)*l3)
    1648              : 
    1649              :              ! FIXME :TO BE CLARIFIED:
    1650              :              ! We are not working on the G-sphere thus SG may be outside
    1651              :              ! of the box. This check is not done in irrzg!!!
    1652              :              if ( (j1 > n1/2 .or. j1 < -(n1-1)/2) .or. &
    1653     68179142 :                   (j2 > n2/2 .or. j1 < -(n2-1)/2) .or. &
    1654              :                   (j3 > n3/2 .or. j3 < -(n3-1)/2) ) then
    1655              :                !write(std_out,*)"got it"
    1656     50844369 :                workg(:, ind1) = zero; cycle
    1657              :              end if
    1658              : 
    1659    204924076 :              tsm1g = [j1,j2,j3] ! +- S^{-1} G
    1660              : 
    1661              :              ! Map into [0,n-1] and then add 1 for array index in [1,n]
    1662     51231019 :              k1=1+mod(n1+mod(j1,n1),n1)
    1663     51231019 :              k2=1+mod(n2+mod(j2,n2),n2)
    1664     51231019 :              k3=1+mod(n3+mod(j3,n3),n3)
    1665              : 
    1666              :              ! Get linear index of rotated point Gj
    1667     51231019 :              ind2 = k1+n1*((k2-1)+n2*(k3-1))
    1668              : 
    1669     51231019 :              if (has_phase) then
    1670              :                ! compute exp(-2*Pi*I*G dot tau) using original G
    1671              :                ! NB: this phase is same as that in irrzg and phnons1, and corresponds
    1672              :                ! to complex conjugate of phase from G to Gj;
    1673              :                ! we use it immediately below, to go _to_ workg_eq(ind1)
    1674    114836952 :                arg = two_pi * dot_product(qpt + tsm1g, tnon)
    1675     28709238 :                phnon1(1) = cos(arg); phnon1(2) = -sin(arg)
    1676              : 
    1677              :                ! rho(Strans*G)=exp(2*Pi*I*(G) dot tau_S) rho(G)
    1678     28709238 :                workg(1, ind1) = phnon1(1) * workg_eq(1, ind2) - phnon1(2) * workg_eq(2, ind2)
    1679     28709238 :                workg(2, ind1) = phnon1(1) * workg_eq(2, ind2) + phnon1(2) * workg_eq(1, ind2)
    1680              :              else
    1681     22521781 :                workg(1, ind1) = workg_eq(1, ind2)
    1682     22521781 :                workg(2, ind1) = workg_eq(2, ind2)
    1683              :              end if
    1684              : 
    1685              :              ! Take complex conjugate if time-reversal is used.
    1686     53958517 :              if (tsign == -1) workg(2, ind1) = -workg(2, ind1)
    1687              :            end do
    1688              :          end do
    1689              :        end do
    1690              : 
    1691    204556376 :        v1g(:,:,ispden) = v1g(:,:,ispden) + workg * symrec_eq(idir, idir_eq)
    1692              :      end do ! ispden
    1693              :    end do ! idir_eq
    1694              :    !if (debug) write(std_out,*)"Used ",cnt," equivalent perturbations"
    1695              : 
    1696              :    ! Get potential in real space (results in v1scf)
    1697         8772 :    do ispden=1,nspden
    1698              :      !call zerosym(v1g(:,:,ispden),cplex,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
    1699         4386 :      call fourdp(cplex,v1g(:,:,ispden),v1scf(:,ispden,pcase),+1,mpi_enreg,nfft,1,ngfft,tim_fourdp0)
    1700              : 
    1701              :      ! IS(q) = q + G0
    1702              :      ! we want q so we have to multiply by exp(iG0r) in real space.
    1703        16731 :      if (any(g0_qpt /= 0)) then
    1704         1802 :        ABI_CHECK_IEQ(cplex, 2, "cplex != 2")
    1705              :        if (debug) write(std_out,*)"Found not zero g0_qpt", g0_qpt ! for idir: ", idir, ", ipert: ", ipert
    1706         1802 :        call times_eigr(g0_qpt, ngfft, nfft, 1, v1scf(:,ispden,pcase))
    1707              :      end if
    1708              :    end do
    1709              : 
    1710         5666 :    if (symv1 == 1) then
    1711              :      if (debug) write(std_out,*)" Calling v1phq_symmetrize"
    1712          376 :      call v1phq_symmetrize(cryst,idir,ipert,symq,ngfft,cplex,nfft,nspden,nsppol,mpi_enreg,v1scf(:,:,pcase))
    1713              :    end if
    1714              :  end do pcase_loop
    1715              : 
    1716         1280 :  ABI_FREE(v1g)
    1717         1280 :  ABI_FREE(workg)
    1718         1280 :  ABI_FREE(workg_eq)
    1719              : 
    1720              :  ! Handle possible error.
    1721        11240 :  if (any(pflag == 0)) then
    1722            0 :    write(std_out,"(2a)")"The following perturbations cannot be recostructed by symmetry for q-point: ",trim(ktoa(qpt))
    1723            0 :    do ipert=1,cryst%natom
    1724            0 :      do idir=1,3
    1725            0 :        if (pflag(idir, ipert) == 0) write(std_out,"(2(a,i0))")"idir= ",idir,", ipert= ",ipert
    1726              :      end do
    1727              :    end do
    1728              :    write(msg,"(5a)")&
    1729            0 :      "Cannot recostruct all 3*natom atomic perturbations from file",ch10,&
    1730            0 :      "This usually happens when the DVDB does not contain all the independent perturbations for this q-point",ch10,&
    1731            0 :      "See above message for further information."
    1732            0 :    ABI_ERROR(msg)
    1733              :  end if
    1734              : 
    1735         1280 : end subroutine v1phq_complete
    1736              : !!***
    1737              : 
    1738              : !----------------------------------------------------------------------
    1739              : 
    1740              : !!****f* m_dvdb/find_symeq
    1741              : !! NAME
    1742              : !! find_symeq
    1743              : !!
    1744              : !! FUNCTION
    1745              : !!  Find symmetry which links to the perturbation specified by (idir, ipert)
    1746              : !!
    1747              : !! INPUTS
    1748              : !!  cryst<crystal_t>=crystal structure parameters
    1749              : !!  idir=Direction of the perturbation
    1750              : !!  ipert=Perturbation type.
    1751              : !!  symq(4,2,nsym)=Table produced by littlegroup_q for this q-point.
    1752              : !!  pflag(3,natom)= For each atomic perturbation:
    1753              : !!     0 if pert is not available. 1 if pert is available. 2 if pert can been reconstructed by symmetry.
    1754              : !!
    1755              : !! OUTPUT
    1756              : !!  ipert_eq
    1757              : !!  isym_eq
    1758              : !!  itirev_eq
    1759              : !!  g0_qpt(3)
    1760              : !!
    1761              : !! SOURCE
    1762              : 
    1763         4386 : subroutine find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0)
    1764              : 
    1765              : !Arguments ------------------------------------
    1766              : !scalars
    1767              :  integer,intent(in) :: idir,ipert
    1768              :  integer,intent(out) :: ipert_eq,isym_eq,itirev_eq
    1769              :  type(crystal_t),intent(in) :: cryst
    1770              :  logical,optional :: allow_g0
    1771              : !arrays
    1772              :  integer,intent(in) :: symq(4,2,cryst%nsym),pflag(3,cryst%natom)
    1773              :  integer,intent(out) :: g0_qpt(3)
    1774              : 
    1775              : !Local variables-------------------------------
    1776              : !scalars
    1777              :  logical :: do_allow_g0
    1778              :  integer :: isym,idir_eq,ip,itirev
    1779              : ! *************************************************************************
    1780              : 
    1781         4386 :  isym_eq = -1; ipert_eq = -1
    1782         4386 :  do_allow_g0 = .true.; if (present(allow_g0)) do_allow_g0 = allow_g0
    1783              : 
    1784              : symloop: &
    1785         4687 :  do itirev=1,2
    1786         4687 :    itirev_eq = itirev
    1787        54562 :    do isym=1,cryst%nsym
    1788              : 
    1789              :      ! Check that isym preserves the q-point
    1790              :      ! The condition is
    1791              :      !
    1792              :      !    $q =  O S(q) - G$
    1793              :      !
    1794              :      ! with O being either the identity or the time reversal symmetry (= inversion in reciprocal space)
    1795              :      ! and G being a primitive vector of the reciprocal lattice.
    1796              : 
    1797              :      !if (symq(4,itirev,isym) /= 1 .or. any(symq(1:3,itirev,isym) /= 0)) cycle
    1798        49875 :      if (symq(4,itirev,isym) /= 1) cycle ! .or. any(symq(1:3,itirev,isym) /= 0)) cycle
    1799        60918 :      if (any(symq(1:3,itirev,isym) /= 0) .and. .not. do_allow_g0) cycle
    1800        72440 :      g0_qpt = symq(1:3,itirev,isym)
    1801              : 
    1802              :      ! indsym map is computed in symatm.
    1803        46354 :      do ip=1,cryst%natom
    1804              :        !if (.not. cryst%indsym(4,isym,ip) == ipert) cycle
    1805        32329 :        if (.not. cryst%indsym(4,isym,ipert) == ip) cycle
    1806        18110 :        isym_eq = isym; ipert_eq = ip
    1807        72440 :        do idir_eq=1,3
    1808        54330 :          if (idir_eq == idir .and. ip == ipert .and. cryst%symrec(idir,idir_eq,isym) /= 0) isym_eq = -1
    1809        72440 :          if (cryst%symrec(idir,idir_eq,isym) /= 0 .and. pflag(idir_eq, ip) == 0) then
    1810              :          !if (cryst%symrel(idir,idir_eq,isym) /= 0 .and. pflag(idir_eq, ip) == 0) then
    1811              :            !if (idir_eq == idir .and. ip == ipert) cycle
    1812        16209 :            isym_eq = -1
    1813              :          end if
    1814              :        end do
    1815        63599 :        if (isym_eq /= -1) exit symloop
    1816              :      end do
    1817              :    end do
    1818              :  end do symloop
    1819              : 
    1820         4386 :  if (isym_eq == -1) then
    1821            0 :    ipert_eq = -1; itirev_eq = -1
    1822              :  end if
    1823              : 
    1824         4386 : end subroutine find_symeq
    1825              : !!***
    1826              : 
    1827              : !----------------------------------------------------------------------
    1828              : 
    1829              : !!****f* m_dvdb/v1phq_rotate
    1830              : !! NAME
    1831              : !! v1phq_rotate
    1832              : !!
    1833              : !! FUNCTION
    1834              : !!  Reconstruct all the DFPT potential for a q-point in the BZ (qpt_bz) starting from its symmetrical image in the IBZ (q_ibz)
    1835              : !!
    1836              : !! INPUTS
    1837              : !!  qpt_ibz(3)=q-point in the IBZ in reduced coordinates.
    1838              : !!  cryst<crystal_t>=crystal structure parameters
    1839              : !!  isym, itimrev, g0q: Symmetry indices and umklapp. The q-point in the BZ is given by:
    1840              : !!
    1841              : !!      qpt_bz = I(itimrev) S(isym) q_ibz + g0q
    1842              : !!
    1843              : !!  where S is symrec(:,:,isym)
    1844              : !!  ngfft=array of dimensions for different FFT grids
    1845              : !!  ngfft(18)=contain all needed information about 3D FFT.
    1846              : !!  cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX
    1847              : !!  nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90)
    1848              : !!  nspden=number of spin-density components
    1849              : !!  mpi_enreg=information about MPI parallelization
    1850              : !!  v1r_qibz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space
    1851              : !!    for the irreducible q-point `qpt_ibz`
    1852              : !!  comm: MPI communicator to distribute natom3 * nspden FFT calls
    1853              : !!
    1854              : !! OUTPUT
    1855              : !!  v1r_qbz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the q-point in the BZ
    1856              : !!
    1857              : !! SOURCE
    1858              : 
    1859         2050 : subroutine v1phq_rotate(cryst, qpt_ibz, isym, itimrev, g0q, ngfft, cplex, nfft, nspden, &
    1860         2050 :                         mpi_enreg, v1r_qibz, v1r_qbz, comm)
    1861              : 
    1862              : !Arguments ------------------------------------
    1863              : !scalars
    1864              :  integer,intent(in) :: isym, itimrev, cplex, nfft, nspden, comm
    1865              :  type(crystal_t),intent(in) :: cryst
    1866              :  type(MPI_type),intent(in) :: mpi_enreg
    1867              : !arrays
    1868              :  integer,intent(in) :: g0q(3),ngfft(18)
    1869              :  real(dp),intent(in) :: qpt_ibz(3)
    1870              :  real(dp),intent(inout) :: v1r_qibz(cplex*nfft,nspden,3*cryst%natom)
    1871              :  real(dp) ABI_ASYNC, intent(out) :: v1r_qbz(cplex*nfft,nspden,3*cryst%natom)
    1872              : 
    1873              : !Local variables-------------------------------
    1874              : !scalars
    1875              :  integer,parameter :: tim_fourdp0 = 0
    1876              :  !integer,save :: enough = 0
    1877              :  integer :: natom3,mu,ispden,idir,ipert,idir_eq,ipert_eq,mu_eq,cnt,tsign,my_rank,nproc,ierr,root
    1878              : !arrays
    1879              :  integer :: symrec_eq(3,3),sm1(3,3),l0(3) !g0_qpt(3), symrel_eq(3,3),
    1880              :  real(dp) :: tnon(3), tsec(2)
    1881         2050 :  real(dp) ABI_ASYNC, allocatable :: v1g_qibz(:,:,:),workg(:,:),v1g_mu(:,:)
    1882         4100 :  integer :: requests(nspden, 3*cryst%natom), requests_v1r_qbz(3*cryst%natom)
    1883         4100 :  logical :: requests_v1g_qibz_done(nspden, 3*cryst%natom)
    1884              : ! *************************************************************************
    1885              : 
    1886              :  ! Keep track of total time spent.
    1887         2050 :  call timab(1804, 1, tsec)
    1888              : 
    1889         2050 :  ABI_CHECK_IEQ(cplex, 2, "cplex != 2")
    1890              : 
    1891         2050 :  nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    1892         2050 :  natom3 = 3 * cryst%natom; tsign = 3-2*itimrev
    1893              : 
    1894              :  ! Compute IBZ potentials in G-space. Results stored in v1g_qibz(G)
    1895        10250 :  ABI_MALLOC(v1g_qibz, (2*nfft, nspden, natom3))
    1896        25612 :  requests_v1g_qibz_done = .False.
    1897              :  cnt = 0
    1898        13831 :  do mu=1,natom3
    1899        25612 :    do ispden=1,nspden
    1900        11781 :      cnt = cnt + 1; root = mod(cnt, nproc)
    1901        11781 :      if (root == my_rank) then ! Non-blocking
    1902        11781 :        call fourdp(cplex, v1g_qibz(:,ispden,mu), v1r_qibz(:,ispden,mu), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0)
    1903              :      end if
    1904        23562 :      call xmpi_ibcast(v1g_qibz(:,ispden,mu), root, comm, requests(ispden, mu), ierr)
    1905              :    end do
    1906              :  end do
    1907              : 
    1908         8200 :  ABI_MALLOC(workg, (2*nfft, nspden))
    1909         6150 :  ABI_MALLOC(v1g_mu, (2*nfft, nspden))
    1910              : 
    1911        26650 :  symrec_eq = cryst%symrec(:,:,isym)
    1912              :  ! Compute sm1 = symrec_eq^{-1}
    1913        51250 :  call mati3inv(symrec_eq, sm1); sm1 = transpose(sm1)
    1914              : 
    1915              :  ! For each perturbation (idir, ipert, qpt_bz), rotate the symmetrical potentials at (idir_eq, ipert_eq, q_ibz)
    1916              :  ! computed in g-space and take linear combinations using symrec_eq(idir, idir_eq).
    1917              :  ! Finally, perform g -- >r FFTs of the potentials at qpt_bz and multiply by e^{-ig0.r} to account for umklapp.
    1918              : 
    1919              :  ! See Eq C2 in [[cite:Brunin2020b]] 10.1103/PhysRevB.102.094308
    1920        13831 :  do mu=1,natom3
    1921        11781 :    root = mod(mu, nproc)
    1922              :    ! MPI parallelism.
    1923        11781 :    if (root == my_rank) then
    1924        11781 :      idir = mod(mu-1, 3) + 1; ipert = (mu - idir) / 3 + 1
    1925              : 
    1926              :      ! Phase due to L0 + R^{-1} tau where R is a symrel operation hence R^{-1} = symrec_eq^T
    1927        47124 :      l0 = cryst%indsym(1:3,isym,ipert)
    1928       329868 :      tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym))
    1929              :      !if (.not. all(abs(tnon) < tol12)) then
    1930              :      !  enough = enough + 1
    1931              :      !  if (enough == 1) ABI_WARNING("tnon must be tested!")
    1932              :      !end if
    1933              : 
    1934        11781 :      ipert_eq = cryst%indsym(4, isym, ipert)
    1935              : 
    1936    236947674 :      v1g_mu = zero; cnt = 0
    1937        47124 :      do idir_eq=1,3
    1938        35343 :        if (symrec_eq(idir, idir_eq) == 0) cycle
    1939        18377 :        mu_eq = idir_eq + (ipert_eq - 1) * 3
    1940        18377 :        cnt = cnt + 1
    1941              : 
    1942              :        ! Wait for request before operating on v1g_qibz
    1943        24973 :        if (.not. all(requests_v1g_qibz_done(:, mu_eq))) then
    1944        23562 :          do ispden=1,nspden
    1945        11781 :            call xmpi_wait(requests(ispden, mu_eq), ierr)
    1946        23562 :            requests_v1g_qibz_done(ispden, mu_eq) = .True.
    1947              :          end do
    1948              :        end if
    1949              : 
    1950              :        ! Rotate in G-space: output in workg
    1951        18377 :        call rotate_fqg(itimrev, sm1, qpt_ibz, tnon, ngfft, nfft, nspden, v1g_qibz(:,:,mu_eq), workg)
    1952              :        ! And accumulate in v1g_mu
    1953    367576854 :        v1g_mu = v1g_mu + workg * symrec_eq(idir, idir_eq)
    1954              :      end do ! idir_eq
    1955              : 
    1956        11781 :      ABI_CHECK(cnt /= 0, "cnt should not be zero!")
    1957              : 
    1958              :      ! Transform to real space and take into account a possible shift. Results are stored in v1r_qbz.
    1959        23562 :      do ispden=1,nspden
    1960        11781 :        call fourdp(cplex, v1g_mu(:, ispden), v1r_qbz(:, ispden, mu), +1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0)
    1961        58905 :        call times_eigr(-g0q, ngfft, nfft, 1, v1r_qbz(:, ispden, mu))
    1962              :        !call times_eigr(tsign * g0q, ngfft, nfft, 1, v1r_qbz(:,ispden,mu))
    1963              :      end do
    1964              : 
    1965              :    end if ! root == myrank
    1966              : 
    1967        13831 :    call xmpi_ibcast(v1r_qbz(:,:,mu), root, comm, requests_v1r_qbz(mu), ierr)
    1968              :  end do ! mu
    1969              : 
    1970              :  ! Release all requests
    1971         2050 :  call xmpi_waitall(requests, ierr)
    1972         2050 :  call xmpi_waitall(requests_v1r_qbz, ierr)
    1973              : 
    1974         2050 :  ABI_FREE(workg)
    1975         2050 :  ABI_FREE(v1g_mu)
    1976         2050 :  ABI_FREE(v1g_qibz)
    1977              : 
    1978         2050 :  call timab(1804, 2, tsec)
    1979              : 
    1980         2050 : end subroutine v1phq_rotate
    1981              : !!***
    1982              : 
    1983              : !----------------------------------------------------------------------
    1984              : 
    1985              : !!****f* m_dvdb/v1phq_rotate_myperts
    1986              : !! NAME
    1987              : !! v1phq_rotate_myperts
    1988              : !!
    1989              : !! FUNCTION
    1990              : !!  Reconstruct all the DFPT potential for a q-point in the BZ starting from its symmetrical image in the IBZ.
    1991              : !!
    1992              : !! INPUTS
    1993              : !!  cryst<crystal_t>=crystal structure parameters
    1994              : !!  qpt_ibz(3)=q-point in the IBZ in reduced coordinates.
    1995              : !!  ngfft=array of dimensions for different FFT grids
    1996              : !!  isym, itimrev, g0q:
    1997              : !!    qpt_bz = I(itimrev) S(isym) q_ibz + g0q
    1998              : !!  ngfft(18)=contain all needed information about 3D FFT.
    1999              : !!  cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX
    2000              : !!  nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90)
    2001              : !!  nspden=number of spin-density components
    2002              : !!  mpi_enreg=information about MPI parallelization
    2003              : !!  v1r_qibz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space
    2004              : !!    for the irreducible q-point `qpt_ibz`
    2005              : !!
    2006              : !! OUTPUT
    2007              : !!  v1r_qbz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the q-point in the BZ
    2008              : !!
    2009              : !! SOURCE
    2010              : 
    2011              : subroutine v1phq_rotate_myperts(cryst, qpt_ibz, isym, itimrev, g0q, ngfft, cplex, nfft, nspden, &
    2012              :                                 mpi_enreg, my_npert, my_pinfo, v1r_qibz, v1r_qbz)
    2013              : 
    2014              : !Arguments ------------------------------------
    2015              : !scalars
    2016              :  integer,intent(in) :: isym, itimrev, cplex, nfft, nspden, my_npert
    2017              :  type(crystal_t),intent(in) :: cryst
    2018              :  type(MPI_type),intent(in) :: mpi_enreg
    2019              : !arrays
    2020              :  integer,intent(in) :: g0q(3), ngfft(18), my_pinfo(3, my_npert)
    2021              :  real(dp),intent(in) :: qpt_ibz(3)
    2022              :  real(dp),intent(inout) :: v1r_qibz(cplex*nfft,nspden,3*cryst%natom)
    2023              :  real(dp),intent(out) :: v1r_qbz(cplex*nfft,nspden,my_npert)
    2024              : 
    2025              : !Local variables-------------------------------
    2026              : !scalars
    2027              :  integer,parameter :: tim_fourdp0 = 0
    2028              :  !integer,save :: enough = 0
    2029              :  integer :: natom3,mu,ispden,idir,ipert,idir_eq,ipert_eq,mu_eq,cnt,tsign,imyp !ierr,
    2030              : !arrays
    2031              :  integer :: symrec_eq(3,3),sm1(3,3),l0(3) !g0_qpt(3), symrel_eq(3,3),
    2032              :  logical :: fourdp_done(3*cryst%natom)
    2033              :  real(dp) :: tnon(3), tsec(2)
    2034              :  real(dp), allocatable :: v1g_qibz(:,:,:),workg(:,:),v1g_mu(:,:)
    2035              : ! *************************************************************************
    2036              : 
    2037              :  ! Keep track of total time spent.
    2038              :  call timab(1804, 1, tsec)
    2039              : 
    2040              :  ABI_CHECK_IEQ(cplex, 2, "cplex != 2")
    2041              : 
    2042              :  natom3 = 3 * cryst%natom; tsign = 3-2*itimrev
    2043              : 
    2044              :  ! Compute IBZ potentials in G-space. Results stored in v1g_qibz(G)
    2045              :  fourdp_done = .False.
    2046              :  ABI_MALLOC(v1g_qibz, (2*nfft, nspden, natom3))
    2047              :  !do mu=1,natom3
    2048              :  !  do ispden=1,nspden
    2049              :  !    call fourdp(cplex, v1g_qibz(:,ispden,mu), v1r_qibz(:,ispden,mu), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0)
    2050              :  !  end do
    2051              :  !end do
    2052              : 
    2053              :  ABI_MALLOC(workg, (2*nfft, nspden))
    2054              :  ABI_MALLOC(v1g_mu, (2*nfft, nspden))
    2055              : 
    2056              :  symrec_eq = cryst%symrec(:,:,isym)
    2057              :  call mati3inv(symrec_eq, sm1); sm1 = transpose(sm1)
    2058              : 
    2059              :  ! For each perturbation treated by this MPI proc
    2060              :  do imyp=1,my_npert
    2061              :    idir = my_pinfo(1, imyp); ipert = my_pinfo(2, imyp); mu = my_pinfo(3, imyp)
    2062              : 
    2063              :    ! Phase due to L0 + R^{-1}tau
    2064              :    l0 = cryst%indsym(1:3,isym,ipert)
    2065              :    tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym))
    2066              :    !if (.not. all(abs(tnon) < tol12)) then
    2067              :    !  enough = enough + 1
    2068              :    !  if (enough == 1) ABI_WARNING("tnon must be tested!")
    2069              :    !end if
    2070              : 
    2071              :    ipert_eq = cryst%indsym(4, isym, ipert)
    2072              : 
    2073              :    v1g_mu = zero; cnt = 0
    2074              :    do idir_eq=1,3
    2075              :      if (symrec_eq(idir, idir_eq) == 0) cycle
    2076              :      mu_eq = idir_eq + (ipert_eq - 1) * 3
    2077              :      cnt = cnt + 1
    2078              : 
    2079              :      if (.not. fourdp_done(mu_eq)) then
    2080              :        do ispden=1,nspden
    2081              :          call fourdp(cplex, v1g_qibz(:,ispden,mu_eq), v1r_qibz(:,ispden,mu_eq), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0)
    2082              :        end do
    2083              :        fourdp_done(mu_eq) = .True.
    2084              :      end if
    2085              : 
    2086              :      ! Rotate in G-space and accumulate in workg
    2087              :      call rotate_fqg(itimrev, sm1, qpt_ibz, tnon, ngfft, nfft, nspden, v1g_qibz(:,:,mu_eq), workg)
    2088              :      v1g_mu = v1g_mu + workg * symrec_eq(idir, idir_eq)
    2089              :    end do ! idir_eq
    2090              : 
    2091              :    ABI_CHECK(cnt /= 0, "cnt should not be zero!")
    2092              : 
    2093              :    ! Transform to real space and take into account a possible shift. Results are stored in v1r_qbz.
    2094              :    do ispden=1,nspden
    2095              :      call fourdp(cplex, v1g_mu(:, ispden), v1r_qbz(:, ispden, imyp), +1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0)
    2096              :      call times_eigr(-g0q, ngfft, nfft, 1, v1r_qbz(:, ispden, imyp))
    2097              :      !call times_eigr(tsign * g0q, ngfft, nfft, 1, v1r_qbz(:,ispden,imyp))
    2098              :    end do
    2099              : 
    2100              :  end do ! imyp
    2101              : 
    2102              :  ABI_FREE(workg)
    2103              :  ABI_FREE(v1g_mu)
    2104              :  ABI_FREE(v1g_qibz)
    2105              : 
    2106              :  call timab(1804, 2, tsec)
    2107              : 
    2108              : end subroutine v1phq_rotate_myperts
    2109              : !!***
    2110              : 
    2111              : !!****f* m_dvdb/v1phq_symmetrize
    2112              : !! NAME
    2113              : !! v1phq_symmetrize
    2114              : !!
    2115              : !! FUNCTION
    2116              : !!  Enforce spatial-symmetry on the DFPT potential.
    2117              : !!
    2118              : !! INPUTS
    2119              : !! cryst<crystal_t>=crystal structure parameters
    2120              : !! idir=Direction of the perturbation
    2121              : !! ipert=Perturbation type.
    2122              : !! symq(4,2,nsym)= Table computed by littlegroup_q.
    2123              : !!   three first numbers define the G vector;
    2124              : !!   fourth number is zero if the q-vector is not preserved, is 1 otherwise
    2125              : !!   second index is one without time-reversal symmetry, two with time-reversal symmetry
    2126              : !! ngfft=array of dimensions for different FFT grids
    2127              : !! cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX
    2128              : !! nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90)
    2129              : !! nspden=number of spin-density components
    2130              : !! mpi_enreg=information about MPI parallelization
    2131              : !!
    2132              : !! SIDE EFFECTS
    2133              : !!  v1r(cplex*nfft,nspden)=Array with first order potentials in real space. Symmetrized in output.
    2134              : !!
    2135              : !! SOURCE
    2136              : 
    2137         1718 : subroutine v1phq_symmetrize(cryst, idir, ipert, symq, ngfft, cplex, nfft, nspden, nsppol, mpi_enreg, v1r)
    2138              : 
    2139              : !Arguments ------------------------------------
    2140              : !scalars
    2141              :  integer,intent(in) :: idir, ipert, cplex, nfft, nspden, nsppol
    2142              :  type(crystal_t),intent(in) :: cryst
    2143              :  type(MPI_type),intent(in) :: mpi_enreg
    2144              : !arrays
    2145              :  integer,intent(in) :: symq(4,2,cryst%nsym),ngfft(18)
    2146              :  real(dp),intent(inout) :: v1r(cplex*nfft,nspden)
    2147              : 
    2148              : !Local variables-------------------------------
    2149              :  integer,parameter :: syuse0 = 0, rfmeth2 = 2, iscf1 = 1
    2150              :  integer :: nsym1, nfftot
    2151              : !arrays
    2152         3436 :  integer :: symafm1(cryst%nsym),symrel1(3,3,cryst%nsym),symrc1(3,3,cryst%nsym)
    2153         1718 :  integer,allocatable :: irrzon1(:,:,:),indsy1(:,:,:)
    2154            0 :  real(dp) :: tnons1(3,cryst%nsym)
    2155         1718 :  real(dp),allocatable :: phnons1(:,:,:),v1g(:,:)
    2156              : ! *************************************************************************
    2157              : 
    2158         1718 :  if (cryst%nsym == 1) return
    2159              : 
    2160         6872 :  nfftot = product(ngfft(1:3))
    2161         1718 :  ABI_CHECK(nfft == nfftot, "MPI-FFT not coded")
    2162              : 
    2163              :  ! Symmetrize (copied from dfpt_looppert)
    2164              :  ! Determines the set of symmetries that leaves the perturbation invariant.
    2165              :  call littlegroup_pert(cryst%gprimd,idir,cryst%indsym,dev_null,ipert,cryst%natom,cryst%nsym,nsym1,rfmeth2,&
    2166         1718 :    cryst%symafm,symafm1,symq,cryst%symrec,cryst%symrel,symrel1,syuse0,cryst%tnons,tnons1,unit=dev_null)
    2167              : 
    2168              :  ! Set up corresponding symmetry data
    2169         6872 :  ABI_MALLOC(irrzon1, (nfft**(1-1/nsym1),2,(nspden/nsppol)-3*(nspden/4)))
    2170         6872 :  ABI_MALLOC(phnons1, (2,nfft**(1-1/nsym1),(nspden/nsppol)-3*(nspden/4)))
    2171         6872 :  ABI_MALLOC(indsy1,(4,nsym1,cryst%natom))
    2172              : 
    2173              :  call setsym(indsy1,irrzon1,iscf1,cryst%natom,nfft,ngfft,nspden,nsppol,&
    2174         1718 :              nsym1,phnons1,symafm1,symrc1,symrel1,tnons1,cryst%typat,cryst%xred)
    2175              : 
    2176              :  !if (psps%usepaw==1) then
    2177              :  !  ! Allocate/initialize only zarot in pawang1 datastructure
    2178              :  !  call pawang_init(pawang1,0,0,pawang%l_max-1,0,0,nsym1,0,0,0,0)
    2179              :  !  call setsym_ylm(gprimd,pawang1%l_max-1,pawang1%nsym,0,rprimd,symrc1,pawang1%zarot)
    2180              :  !end if
    2181              : 
    2182              :  ! FIXME Be careful here because symrhg was written for densities!
    2183         1718 :  ABI_CHECK(nsppol == 1 .and. nspden == 1, "symrhg was written for densities, not for potentials")
    2184              : 
    2185         5154 :  ABI_MALLOC(v1g, (2,nfft))
    2186              :  call symrhg(cplex,cryst%gprimd,irrzon1,mpi_enreg,nfft,nfftot,ngfft,nspden,nsppol,nsym1,&
    2187         1718 :              phnons1,v1g,v1r,cryst%rprimd,symafm1,symrel1,tnons1)
    2188              : 
    2189         1718 :  ABI_FREE(irrzon1)
    2190         1718 :  ABI_FREE(phnons1)
    2191         1718 :  ABI_FREE(indsy1)
    2192         1718 :  ABI_FREE(v1g)
    2193              : 
    2194              : end subroutine v1phq_symmetrize
    2195              : !!***
    2196              : 
    2197              : !----------------------------------------------------------------------
    2198              : 
    2199              : !!****f* m_dvdb/rotate_fqg
    2200              : !! NAME
    2201              : !!  rotate_fqg
    2202              : !!
    2203              : !! FUNCTION
    2204              : !!  Rotate density/potential infg_q(g) in g-space to obtain outfg_{ISq}(g)
    2205              : !!
    2206              : !! INPUTS
    2207              : !!  itirev=2 if time-reversal symmetry should be used, 1 otherwise.
    2208              : !!  symm(3,3)=Symmetry operation S in reciprocal space.
    2209              : !!    NB: symm usually corresponds to the inverso of one of the symrec operations.
    2210              : !!  qpt(3)=q-point in the IBZ (this is the q-point associated to infg)
    2211              : !!  tnon(3)=Fractional translation associate the the symmetry operation.
    2212              : !!  ngfft(18)=contain all needed information about 3D FFT.
    2213              : !!  nfft=Number of fft-points treated by this processors
    2214              : !!  nspden=number of spin-density components
    2215              : !!  infg(2,nfft,nspden)=Input array in g-space on the FFT box.
    2216              : !!
    2217              : !! OUTPUTS
    2218              : !!   outfg(2,nfft,nspden)= Input array in g-space on the FFT box. In pseudo-equation:
    2219              : !!
    2220              : !!     outfg(g) = infg(IS G) e^{-i(IS^{-1} G)} exp(2*pi*I*(G) dot tau_S) rho(IS^{-1} G)
    2221              : !!
    2222              : !! SOURCE
    2223              : 
    2224        18377 : subroutine rotate_fqg(itirev, symm, qpt, tnon, ngfft, nfft, nspden, infg, outfg)
    2225              : 
    2226              : !Arguments ------------------------------------
    2227              : !scalars
    2228              :  integer,intent(in) :: itirev,nfft,nspden
    2229              : !arrays
    2230              :  integer,intent(in) :: symm(3,3),ngfft(18)
    2231              :  real(dp),intent(in) :: qpt(3),tnon(3)
    2232              :  real(dp),intent(in) :: infg(2,nfft,nspden)
    2233              :  real(dp),intent(out) :: outfg(2,nfft,nspden)
    2234              : 
    2235              : !Local variables-------------------------------
    2236              : !scalars
    2237              :  integer :: i1,i2,i3,id1,id2,id3,n1,n2,n3,ind1,ind2,j1,j2,j3,l1,l2,l3,k1,k2,k3,nfftot,isp,tsign
    2238              :  real(dp) :: arg
    2239              :  logical :: has_phase
    2240              : !arrays
    2241              :  integer :: tsg(3)
    2242              :  real(dp) :: phnon1(2), tsec(2)
    2243              : ! *************************************************************************
    2244              : 
    2245              :  ! Keep track of total time spent.
    2246        18377 :  call timab(1803, 1, tsec)
    2247              : 
    2248        73508 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3))
    2249        18377 :  ABI_CHECK(nfftot == nfft, "FFT parallelism not supported")
    2250        18377 :  id1 = n1/2+2; id2 = n2/2+2; id3=n3/2+2
    2251              : 
    2252        18377 :  ABI_CHECK(any(itirev == [1, 2]), "Wrong itirev")
    2253        53619 :  tsign = 3-2*itirev; has_phase = any(abs(tnon) > tol12)
    2254              : 
    2255              :  !outfg = zero
    2256              : 
    2257        36754 :  do isp=1,nspden
    2258              :    ind1 = 0
    2259       376070 :    do i3=1,n3
    2260              :      ! Get location of G vector (grid point) centered at 0 0 0
    2261       339316 :      l3 = i3-(i3/id3)*n3-1
    2262      7781485 :      do i2=1,n2
    2263      7423792 :        l2 = i2-(i2/id2)*n2-1
    2264    191509596 :        do i1=1,n1
    2265    183746488 :          ind1 = ind1 + 1
    2266              :          !ind1 = 1 + i1 + (i2-1)*n1 + (i3-1)*n1*n2
    2267              :          !if (mod(ind1, nprocs) /= my_rank) cycle
    2268              : 
    2269    183746488 :          l1 = i1-(i1/id1)*n1-1
    2270              : 
    2271              :          ! Get rotated G vector: IS(G)
    2272    183746488 :          j1 = tsign * (symm(1,1)*l1+symm(1,2)*l2+symm(1,3)*l3)
    2273    183746488 :          j2 = tsign * (symm(2,1)*l1+symm(2,2)*l2+symm(2,3)*l3)
    2274    183746488 :          j3 = tsign * (symm(3,1)*l1+symm(3,2)*l2+symm(3,3)*l3)
    2275              : 
    2276              :          ! FIXME :TO BE CLARIFIED:
    2277              :          ! We are not working on the G-sphere thus SG may be outside
    2278              :          ! of the box. This check is not done in irrzg!!!
    2279              :          if ( (j1 > n1/2 .or. j1 < -(n1-1)/2) .or. &
    2280    183746488 :               (j2 > n2/2 .or. j1 < -(n2-1)/2) .or. &
    2281              :               (j3 > n3/2 .or. j3 < -(n3-1)/2) ) then
    2282              :            !write(std_out,*)"outsize box!"
    2283    176108448 :            outfg(:,ind1,isp) = zero
    2284              :            cycle
    2285              :          end if
    2286              : 
    2287    500174688 :          tsg = [j1,j2,j3] ! IS^{-1} G
    2288              : 
    2289              :          ! Map into [0,n-1] and then add 1 for array index in [1, n]
    2290    125043672 :          k1=1+mod(n1+mod(j1,n1),n1)
    2291    125043672 :          k2=1+mod(n2+mod(j2,n2),n2)
    2292    125043672 :          k3=1+mod(n3+mod(j3,n3),n3)
    2293              : 
    2294              :          ! Get linear index of rotated point Gj
    2295    125043672 :          ind2 = k1+n1*((k2-1)+n2*(k3-1))
    2296              : 
    2297              :          ! TODO: Here I believe there are lots of cache misses, should perform low-level profiling
    2298              :          ! OMP perhaps can accelerate this part but mind false sharing...
    2299    125043672 :          if (has_phase) then
    2300              :            ! compute exp(-2*pi*I*G dot tau_S) using original G
    2301    240549132 :            arg = two_pi * dot_product(qpt + tsg, tnon)
    2302     60137283 :            phnon1(1) = cos(arg); phnon1(2) =-sin(arg)
    2303              : 
    2304              :            ! rho(Strans*G)=exp(2*pi*IG dot tau_S) rho(G)
    2305     60137283 :            outfg(1, ind1, isp) = phnon1(1) * infg(1, ind2, isp) - phnon1(2) * infg(2, ind2, isp)
    2306     60137283 :            outfg(2, ind1, isp) = phnon1(1) * infg(2, ind2, isp) + phnon1(2) * infg(1, ind2, isp)
    2307              :          else
    2308     64906389 :            outfg(1, ind1, isp) = infg(1, ind2, isp)
    2309     64906389 :            outfg(2, ind1, isp) = infg(2, ind2, isp)
    2310              :          end if
    2311              : 
    2312              :          ! Take complex conjugate if time-reversal is used.
    2313    132467464 :          if (tsign == -1) outfg(2, ind1, isp) = -outfg(2, ind1, isp)
    2314              :        end do
    2315              :      end do
    2316              :    end do
    2317              :  end do ! isp
    2318              : 
    2319              :  !call xmpi_sum(comm, outfg, ierr)
    2320        18377 :  call timab(1803, 2, tsec)
    2321              : 
    2322        18377 : end subroutine rotate_fqg
    2323              : !!***
    2324              : 
    2325              : !----------------------------------------------------------------------
    2326              : 
    2327              : !!****f* m_dvdb/dvdb_ftinterp_setup
    2328              : !! NAME
    2329              : !!  dvdb_ftinterp_setup
    2330              : !!
    2331              : !! FUNCTION
    2332              : !!  Precompute the wsr array with the DFPT potential in the supercell
    2333              : !!  required for the Fourier interpolation.
    2334              : !!  This is a collective routine that should be called by all procs inside db%comm.
    2335              : !!
    2336              : !! \begin{equation}
    2337              : !!      \label{eq:dfpt_pot_realspace}
    2338              : !!     W_{\kappa\alpha}(\rr,\RR) = \dfrac{1}{N_\qq} \sum_\qq e^{-i\qq\cdot(\RR - \rr)}\,
    2339              : !!     \partial_{\kappa\alpha\qq}{v^{\text{scf}}}(\rr)
    2340              : !! \end{equation}
    2341              : !!
    2342              : !! INPUTS
    2343              : !!  ngqpt(3)=Divisions of the ab-initio q-mesh.
    2344              : !!  qptopt=option for the generation of q points (defines whether spatial symmetries and/or time-reversal can be used)
    2345              : !!  nqshift=Number of shifts used to generated the ab-initio q-mesh.
    2346              : !!  qshift(3,nqshift)=The shifts of the ab-initio q-mesh.
    2347              : !!  nfft=Number of fft-points treated by this processors
    2348              : !!  ngfft(18)=contain all needed information about 3D FFT
    2349              : !!  comm_rpt = MPI communicator used to distribute R-lattice points.
    2350              : !!
    2351              : !! SOURCE
    2352              : 
    2353           36 : subroutine dvdb_ftinterp_setup(db, ngqpt, qptopt, nqshift, qshift, nfft, ngfft, comm_rpt)
    2354              : 
    2355              : !Arguments ------------------------------------
    2356              : !scalars
    2357              :  class(dvdb_t),target,intent(inout) :: db
    2358              :  integer,intent(in) :: qptopt,nqshift,nfft,comm_rpt
    2359              : !arrays
    2360              :  integer,intent(in) :: ngqpt(3), ngfft(18)
    2361              :  real(dp),intent(in) :: qshift(3,nqshift)
    2362              : 
    2363              : !Local variables-------------------------------
    2364              : !scalars
    2365              :  integer,parameter :: master=0
    2366              :  integer :: iq_ibz,nqibz,iq_bz,nqbz !, timerev_q
    2367              :  integer :: ii,jj,cplex_qibz,ispden,imyp,irpt,idir,ipert,ipc, iqst, itimrev, isym
    2368              :  integer :: ifft, ierr,  my_rstart, my_rstop, iatom
    2369              :  real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all
    2370              :  logical :: isirr_q
    2371              :  character(len=500) :: msg
    2372              : !arrays
    2373              :  integer :: g0q(3)
    2374              :  !integer :: symq(4,2,db%cryst%nsym)
    2375           36 :  integer,allocatable :: indqq(:,:), iperm(:), nqsts(:), iqs_dvdb(:), all_cell(:,:)
    2376              :  real(dp) :: qpt_bz(3)
    2377           36 :  real(dp),allocatable :: qibz(:,:), qbz(:,:), emiqr(:,:), all_rpt(:,:), all_wghatm(:,:,:)
    2378           36 :  real(dp),allocatable :: v1r_qibz(:,:,:,:), v1r_qbz(:,:,:,:), v1r_lr(:,:,:)
    2379           36 :  real(kind=sp), contiguous, pointer :: wsr_ptr(:,:,:,:,:)
    2380              :  logical,parameter :: DEBUG_WSR_IMAG = .False.
    2381           36 :  real(dp),allocatable :: wsi_diag(:,:,:,:)
    2382              : ! *************************************************************************
    2383              : 
    2384              :  ! Set communicator for R-point parallelism.
    2385              :  ! Note that client code is responsible for calling the interpolation routine dvdb_get_ftqbz (R -> q)
    2386              :  ! with all procs inside comm_rpt to avoid MPI deadlocks.
    2387           36 :  db%comm_rpt = comm_rpt; db%nprocs_rpt = xmpi_comm_size(db%comm_rpt); db%me_rpt = xmpi_comm_rank(db%comm_rpt)
    2388              : 
    2389           36 :  if (db%add_lr >= 4) then
    2390            0 :    call wrtout(std_out, " Skipping construction of W(R,r) because add_lr >= 4. Will use LR part only!")
    2391            0 :    return
    2392              :  end if
    2393              : 
    2394           36 :  call cwtime(cpu_all, wall_all, gflops_all, "start")
    2395              : 
    2396              :  call wrtout(std_out, sjoin(ch10, "Building W(R,r) using q-mesh ngqpt: ", ltoa(ngqpt), &
    2397           36 :    ", with nprocs_rpt:", itoa(db%nprocs_rpt)), do_flush=.True.)
    2398           36 :  call wrtout(std_out, sjoin(" Using Gaussian filter with qdamp: ", ftoa(db%qdamp, fmt="(f6.1)")))
    2399           36 :  call wrtout(std_out, "")
    2400           36 :  call wrtout(std_out, " Note: this part may take some time depending on the number of MPI procs, ngqpt and nfft points.")
    2401           36 :  call wrtout(std_out, " Use boxcutmin < 2.0 (> 1.1) to decrease nfft, reduce memory requirements and speedup the calculation.")
    2402              :  !call wrtout(std_out, " Q-mesh shifts:")
    2403              :  !do ii=1,nqshift
    2404              :  !  call wrtout(std_out, ltoa(qshift(:, ii)))
    2405              :  !end do
    2406              : 
    2407              :  call prepare_ftinterp(db, ngqpt, qptopt, nqshift, qshift, &
    2408           36 :                        qibz, qbz, indqq, iperm, nqsts, iqs_dvdb, all_rpt, all_wghatm, db%comm)
    2409              : 
    2410           36 :  nqibz = size(qibz, dim=2); nqbz = size(qbz, dim=2); db%nrtot = size(all_rpt, dim=2)
    2411              : 
    2412              :  ! Distribute R-points inside comm_rpt.
    2413           36 :  call xmpi_split_work(db%nrtot, db%comm_rpt, my_rstart, my_rstop)
    2414              : 
    2415              :  ! Select my_rpoints.
    2416              :  ! Use REMALLOC so that we can call this routine multiple times i.e. for changing add_lr
    2417           36 :  db%my_nrpt = my_rstop - my_rstart + 1
    2418           36 :  ABI_CHECK(db%my_nrpt /= 0, "my_nrpt == 0!")
    2419              : 
    2420          108 :  ABI_REMALLOC(db%my_rpt, (3, db%my_nrpt))
    2421         5036 :  db%my_rpt = all_rpt(:, my_rstart:my_rstop)
    2422          108 :  ABI_REMALLOC(db%my_irpt2tot, (db%my_nrpt))
    2423         1277 :  do irpt=1,db%my_nrpt
    2424         1277 :    db%my_irpt2tot(irpt) = my_rstart + (irpt - 1)
    2425              :  end do
    2426              : 
    2427              :  ! Copy weights for the atoms treated by this proc.
    2428          462 :  ii = minval(db%my_pinfo(2,:)); jj = maxval(db%my_pinfo(2,:))
    2429          144 :  ABI_REMALLOC(db%my_wratm, (db%my_nrpt, ii:jj))
    2430         2581 :  db%my_wratm = one
    2431           36 :  if (db%rspace_cell == 1) then
    2432            0 :    do iatom=1,db%cryst%natom
    2433            0 :      if (iatom >= ii .and. iatom <= jj) db%my_wratm(:, iatom) = all_wghatm(iatom, iatom, my_rstart:my_rstop)
    2434              :    end do
    2435              :  end if
    2436              : 
    2437           36 :  write(std_out, "(a, i0)")" Using rspace_cell method for integration weights: ", db%rspace_cell
    2438           36 :  write(std_out, "(a, i0)")" Total number of R-points in real-space big box: ", db%nrtot
    2439           36 :  write(std_out, "(a, i0)")" Number of R-points treated by this MPI rank: ", db%my_nrpt
    2440           36 :  write(std_out, "(a, 3(i0, 1x))")" ngfft: ", ngfft(1:3)
    2441           36 :  write(std_out, "(a, i0)")" dvdb_add_lr: ", db%add_lr
    2442              : 
    2443              :  ! Allocate potential in the supercell. Memory is MPI-distributed over my_nrpt and my_npert
    2444              :  call wrtout(std_out, sjoin(" Memory required for W(R,r): ", &
    2445           36 :             ftoa(two * db%my_nrpt * nfft * db%nspden * db%my_npert * sp * b2Mb, fmt="f8.1"), "[Mb] <<< MEM"))
    2446              : 
    2447              :  ABI_SFREE(all_cell)
    2448           36 :  ABI_SFREE(all_wghatm)
    2449           36 :  ABI_FREE(all_rpt)
    2450              : 
    2451          108 :  ABI_MALLOC(emiqr, (2, db%my_nrpt))
    2452          180 :  ABI_MALLOC(v1r_qbz, (2, nfft, db%nspden, db%natom3))
    2453      8410533 :  ABI_CALLOC(v1r_lr, (2, nfft, db%my_npert))
    2454              : 
    2455           36 :  ABI_SFREE(db%wsr)
    2456          216 :  ABI_MALLOC_OR_DIE(db%wsr, (1, db%my_nrpt, nfft, db%nspden, db%my_npert), ierr)
    2457    138868110 :  db%wsr = zero
    2458              : 
    2459              :  if (DEBUG_WSR_IMAG) then
    2460              :    ABI_MALLOC(wsi_diag, (db%my_nrpt, nfft, db%nspden, db%my_npert))
    2461              :    wsi_diag = zero
    2462              :  end if
    2463              : 
    2464              :  ! TODO: Parallelize this part over q-points using comm_rpt. For the time being only pert parallelism.
    2465           36 :  iqst = 0
    2466          237 :  do iq_ibz=1,nqibz
    2467          201 :    call cwtime(cpu, wall, gflops, "start")
    2468              :    !
    2469              :    ! Here all procs get all potentials for this IBZ q-point on the real-space FFT mesh.
    2470              :    ! This call allocates v1r_qibz(cplex_qibz, nfft, nspden, 3*natom)
    2471              :    ! Note that here we need all 3*natom perturbations because of v1phq_rotate.
    2472          201 :    call db%readsym_allv1(iqs_dvdb(iq_ibz), cplex_qibz, nfft, ngfft, v1r_qibz, db%comm)
    2473              : 
    2474              :    ! Reconstruct by symmetry the potentials for the star of this q-point,
    2475              :    ! perform slow FT and accumulate in wsr. Be careful with the gamma point.
    2476         1442 :    do ii=1,nqsts(iq_ibz)
    2477         1241 :      iqst = iqst + 1
    2478              :      !if (mod(ii, nproc) /= my_rank) cycle ! MPI parallelism.
    2479         1241 :      iq_bz = iperm(iqst)
    2480         1241 :      ABI_CHECK(iq_ibz == indqq(1, iq_bz), "iq_ibz !/ indqq(1)")
    2481         4964 :      qpt_bz = qbz(:, iq_bz)
    2482              :      !if (all(abs(qpt_bz) < tol12)) cycle
    2483              :      ! IS(q_ibz) + g0q = q_bz
    2484         4964 :      isym = indqq(2, iq_bz); itimrev = indqq(6, iq_bz) + 1; g0q = indqq(3:5, iq_bz)
    2485         4182 :      isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0))
    2486              :      !write(std_out, *)"qbz", trim(ktoa(qpt_bz)), " --> qibz ", trim(ktoa(qibz(:,iq_ibz)))
    2487              :      !write(std_out, *)"via isym, itimrev, g0q:", isym, itimrev, g0q
    2488              : 
    2489              :      ! Compute long-range part of the coupling potential at qpt_bz.
    2490         1241 :      if (db%add_lr /= 0) then
    2491         7959 :        do imyp=1,db%my_npert
    2492         6822 :          idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp)
    2493         7959 :          call db%get_v1r_long_range(qpt_bz, idir, ipert, nfft, ngfft, v1r_lr(:,:,imyp))
    2494              :        end do
    2495              :      end if
    2496              : 
    2497         1442 :      if (cplex_qibz == 1) then
    2498              :        ! Gamma point.
    2499           36 :        ABI_CHECK(nqsts(iq_ibz) == 1, "cplex_qibz == 1 and nq nqst /= 1 (should be gamma)")
    2500          144 :        ABI_CHECK(all(g0q == 0), "gamma point with g0q /= 0")
    2501              : 
    2502           36 :        if (db%add_lr /= 0) then
    2503              :          ! Subtract the long-range part of the potential.
    2504          161 :          do imyp=1,db%my_npert
    2505          138 :            ipc = db%my_pinfo(3, imyp)
    2506          299 :            do ispden=1,db%nspden
    2507       961668 :              v1r_qibz(1, :, ispden, ipc) = v1r_qibz(1, :, ispden, ipc) - v1r_lr(1, :, imyp)
    2508              :            end do
    2509              :          end do
    2510              :        end if
    2511              : 
    2512              :        ! Slow FT.
    2513          249 :        do imyp=1,db%my_npert
    2514          213 :          ipc = db%my_pinfo(3, imyp)
    2515          462 :          do ispden=1,db%nspden
    2516      2803818 :            do ifft=1,nfft
    2517     70835733 :              do irpt=1,db%my_nrpt
    2518              :                db%wsr(1, irpt, ifft, ispden, imyp) = db%wsr(1, irpt, ifft, ispden, imyp) + &
    2519     70835520 :                                                    v1r_qibz(1, ifft, ispden, ipc)
    2520              :              end do
    2521              :            end do
    2522              :          end do
    2523              :        end do
    2524              : 
    2525              :      else
    2526              :        ! q /= Gamma. Get the periodic part of the potential in BZ (v1r_qbz)
    2527         1205 :        if (isirr_q) then
    2528     33744234 :          v1r_qbz = v1r_qibz
    2529              :        else
    2530              :          call v1phq_rotate(db%cryst, qibz(:,iq_ibz), isym, itimrev, g0q, &
    2531         1040 :                            ngfft, cplex_qibz, nfft, db%nspden, db%mpi_enreg, v1r_qibz, v1r_qbz, xmpi_comm_self)
    2532              :        end if
    2533              : 
    2534              :        ! Multiply by e^{iqpt_bz.r}
    2535         1205 :        call times_eikr(qpt_bz, ngfft, nfft, db%nspden * db%natom3, v1r_qbz)
    2536              : 
    2537         1205 :        if (db%add_lr /= 0) then
    2538              :          ! Subtract the long-range part of the potential.
    2539         7798 :          do imyp=1,db%my_npert
    2540         6684 :            ipc = db%my_pinfo(3, imyp)
    2541        14482 :            do ispden=1,db%nspden
    2542    157017576 :              v1r_qbz(:, :, ispden, ipc) = v1r_qbz(:, :, ispden, ipc) - v1r_lr(:, :, imyp)
    2543              :            end do
    2544              :          end do
    2545              :        end if
    2546              : 
    2547              :        ! Compute FT phases for this qpt_bz.
    2548         4820 :        call calc_eiqr(-qpt_bz, db%my_nrpt, db%my_rpt, emiqr)
    2549              : 
    2550              :        ! Slow FT.
    2551         8414 :        do imyp=1,db%my_npert
    2552         7209 :          ipc = db%my_pinfo(3, imyp)
    2553        15623 :          do ispden=1,db%nspden
    2554     65243154 :            do ifft=1,nfft
    2555              :              db%wsr(1, :, ifft, ispden, imyp) = db%wsr(1, :, ifft, ispden, imyp) &
    2556              :                 + emiqr(1, :) * v1r_qbz(1, ifft, ispden, ipc) &
    2557   3408342336 :                 - emiqr(2, :) * v1r_qbz(2, ifft, ispden, ipc)
    2558              : 
    2559         7209 :              if (DEBUG_WSR_IMAG) then
    2560              :                wsi_diag(:, ifft, ispden, imyp) = wsi_diag(:, ifft, ispden, imyp) &
    2561              :                   + emiqr(1, :) * v1r_qbz(2, ifft, ispden, ipc) &
    2562              :                   + emiqr(2, :) * v1r_qbz(1, ifft, ispden, ipc)
    2563              :              end if
    2564              :            end do
    2565              : 
    2566              :            !call zgerc(db%my_nrpt, nfft, cone, emiqr, 1, v1r_qbz(:,:,ispden,ipc), 1, &
    2567              :            !           db%wsr(:,:,:,ispden,imyp), db%my_nrpt)
    2568              : 
    2569              :          end do ! ispden
    2570              :        end do ! imyp
    2571              :      end if
    2572              : 
    2573              :    end do ! iqst
    2574              : 
    2575          201 :    write(msg,'(2(a,i0),a)') " IBZ q-point [", iq_ibz, "/", nqibz, "]"
    2576          201 :    call cwtime_report(msg, cpu, wall, gflops)
    2577          438 :    ABI_FREE(v1r_qibz)
    2578              :  end do ! iq_ibz
    2579              : 
    2580           36 :  ABI_CHECK(iqst == nqbz, "iqst /= nqbz")
    2581           36 :  call wrtout(std_out, ch10//ch10)
    2582              : 
    2583           36 :  ABI_FREE(iperm)
    2584           36 :  ABI_FREE(emiqr)
    2585           36 :  ABI_FREE(qibz)
    2586           36 :  ABI_FREE(qbz)
    2587           36 :  ABI_FREE(indqq)
    2588           36 :  ABI_FREE(iqs_dvdb)
    2589           36 :  ABI_FREE(nqsts)
    2590           36 :  ABI_FREE(v1r_qbz)
    2591           36 :  ABI_FREE(v1r_lr)
    2592              : 
    2593              :  !call xmpi_sum(db%wsr, db%comm, ierr)
    2594    138868110 :  db%wsr = db%wsr / nqbz
    2595              : 
    2596              :  if (DEBUG_WSR_IMAG) then
    2597              :    wsi_diag = wsi_diag / nqbz
    2598              :    write(std_out, "(a)")" --- DEBUG_WSR_IMAG: discarded Im[W(R,r)] vs kept Re[W(R,r)], per perturbation (imyp) ---"
    2599              :    do imyp=1,db%my_npert
    2600              :      idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp)
    2601              :      write(std_out, "(a,i0,a,i0,a,i0,a,es12.4,a,es12.4)") &
    2602              :        " imyp=", imyp, " idir=", idir, " ipert=", ipert, &
    2603              :        "  max|Im[wsr]|=", maxval(abs(wsi_diag(:,:,:,imyp))), &
    2604              :        "  max|Re[wsr]|=", maxval(abs(real(db%wsr(1,:,:,:,imyp), kind=dp)))
    2605              :    end do
    2606              :    ABI_FREE(wsi_diag)
    2607              :  end if
    2608              : 
    2609           36 :  wsr_ptr => db%wsr
    2610              : #ifdef HAVE_OPENMP_OFFLOAD
    2611              :  ! Upload wsr array to GPU
    2612              :  !$OMP TARGET ENTER DATA MAP(to:wsr_ptr) IF (db%gpu_option==ABI_GPU_OPENMP)
    2613              : #endif
    2614              : 
    2615           36 :  call cwtime_report(" Construction of W(R,r)", cpu_all, wall_all, gflops_all)
    2616              : 
    2617          144 : end subroutine dvdb_ftinterp_setup
    2618              : !!***
    2619              : 
    2620              : !----------------------------------------------------------------------
    2621              : 
    2622              : !!****f* m_dvdb/dvdb_get_maxw
    2623              : !! NAME
    2624              : !!  dvdb_get_maxw
    2625              : !!
    2626              : !! FUNCTION
    2627              : !!   Compute max_r |W(R,r)|
    2628              : !!
    2629              : !! INPUTS
    2630              : !!
    2631              : !! FUNCTION
    2632              : 
    2633            1 : subroutine dvdb_get_maxw(db, ngqpt, all_rpt, all_rmod, maxw)
    2634              : 
    2635              : !Arguments ------------------------------------
    2636              : !scalars
    2637              :  class(dvdb_t),intent(in) :: db
    2638              :  integer,intent(in) :: ngqpt(3)
    2639              :  real(dp),allocatable,intent(out) :: maxw(:,:), all_rpt(:,:), all_rmod(:)
    2640              : 
    2641              : !Local variables-------------------------------
    2642              : !scalars
    2643              :  integer :: imyp, ipc, irpt, irpt_tot, ifft, nfft, ispden, ierr, ii
    2644              :  real(dp) :: phre
    2645              : !arrays
    2646            1 :  integer,allocatable :: iperm_irpt(:)
    2647              :  real(dp) :: sc_rprimd(3,3)
    2648              : ! *************************************************************************
    2649              : 
    2650            1 :  ABI_CHECK(allocated(db%wsr), "wsr is not allocated (call dvdb_ftinterp_setup)")
    2651              : 
    2652            1 :  nfft = size(db%wsr, dim=3)
    2653           58 :  ABI_CALLOC(maxw, (db%nrtot, db%natom3))
    2654              : 
    2655              :  ! Need all RPTs to sort output.
    2656           35 :  ABI_CALLOC(all_rpt, (3, db%nrtot))
    2657            9 :  do irpt=1,db%my_nrpt
    2658            8 :    irpt_tot = db%my_irpt2tot(irpt)
    2659           33 :    all_rpt(:, irpt_tot) = db%my_rpt(:, irpt)
    2660              :  end do
    2661            1 :  call xmpi_sum(all_rpt, db%comm_rpt, ierr)
    2662              : 
    2663            7 :  do imyp=1,db%my_npert
    2664            6 :    ipc = db%my_pinfo(3, imyp)
    2665           55 :    do irpt=1,db%my_nrpt
    2666           48 :      irpt_tot = db%my_irpt2tot(irpt)
    2667           48 :      phre = zero
    2668           96 :      do ispden=1,db%nspden
    2669       196704 :        do ifft=1,nfft
    2670       196656 :          phre = max(phre, real(db%wsr(1,irpt,ifft,ispden,imyp), kind=dp) ** 2) ! + db%wsr(2,irpt,ifft,ispden,imyp) ** 2)
    2671              :        end do
    2672              :      end do
    2673           54 :      maxw(irpt_tot, ipc) = sqrt(phre)
    2674              :    end do
    2675              :  end do
    2676              : 
    2677              :  ! Handle parallelism
    2678            1 :  if (db%nprocs_rpt /= 1) call xmpi_sum(maxw, db%comm_rpt, ierr)
    2679            1 :  if (db%nprocs_pert /= 1) call xmpi_sum(maxw, db%comm_pert, ierr)
    2680              : 
    2681            1 :  sc_rprimd(:, 1) = ngqpt(1) * db%cryst%rprimd(:, 1)
    2682              :  sc_rprimd(:, 2) = ngqpt(2) * db%cryst%rprimd(:, 2)
    2683              :  sc_rprimd(:, 3) = ngqpt(3) * db%cryst%rprimd(:, 3)
    2684            1 :  call sort_rpts(db%nrtot, all_rpt, db%cryst%rmet, iperm_irpt, rmod=all_rmod)
    2685              : 
    2686              :  ! Sort output results by |R|.
    2687           66 :  all_rpt = all_rpt(:, iperm_irpt(:))
    2688            7 :  do ii=1,db%natom3
    2689          103 :    maxw(:, ii) = maxw(iperm_irpt(:), ii)
    2690              :  end do
    2691              : 
    2692            1 :  ABI_FREE(iperm_irpt)
    2693              : 
    2694            1 : end subroutine dvdb_get_maxw
    2695              : !!***
    2696              : 
    2697              : !----------------------------------------------------------------------
    2698              : 
    2699              : !!****f* m_dvdb/prepare_ftinterp
    2700              : !! NAME
    2701              : !!  prepare_ftinterp
    2702              : !!
    2703              : !! FUNCTION
    2704              : !!  Helper function used to prepare the Fourier interpolation of the DFPT potentials.
    2705              : 
    2706           36 : subroutine prepare_ftinterp(db, ngqpt, qptopt, nqshift, qshift, &
    2707              :                             qibz, qbz, indqq, iperm, nqsts, iqs_dvdb, all_rpt, all_wghatm, comm)
    2708              : 
    2709              : !Arguments ------------------------------------
    2710              : !scalars
    2711              :  integer,intent(in) :: nqshift, qptopt, comm
    2712              :  class(dvdb_t),target,intent(in) :: db
    2713              : !arrays
    2714              :  integer,intent(in) :: ngqpt(3)
    2715              :  real(dp),intent(in) :: qshift(3,nqshift)
    2716              :  integer,allocatable,intent(out) :: indqq(:,:), nqsts(:), iqs_dvdb(:), iperm(:)
    2717              :  real(dp),allocatable,intent(out) :: all_rpt(:,:), all_wghatm(:,:,:)
    2718              :  real(dp),allocatable,intent(out) :: qibz(:,:),qbz(:,:)
    2719              : 
    2720              : !Local variables-------------------------------
    2721              : !scalars
    2722              :  integer,parameter :: cutmode2 = 2
    2723              :  integer :: iq_ibz,nqibz,iq_bz,nqbz,ii,iq_dvdb
    2724              :  integer :: iqst,nqst,ix,iy,iz,nq1,nq2,nq3,r1,r2,r3, nrtot
    2725              :  real(dp) :: r_inscribed_sphere
    2726              :  logical :: found
    2727              :  character(len=500) :: msg
    2728              :  type(crystal_t),pointer :: cryst
    2729           36 :  type(krank_t) :: qrank
    2730              : !arrays
    2731              :  integer :: qptrlatt(3,3)
    2732           36 :  integer,allocatable :: bz2ibz_sort(:),all_cell(:,:)
    2733           72 :  real(dp) :: shift(3), rcan(3, db%cryst%natom), trans(3, db%cryst%natom), acell(3), rprim(3,3), gprim(3,3)
    2734           36 :  real(dp),allocatable :: wtq(:),all_rcart(:,:)
    2735              : ! *************************************************************************
    2736              : 
    2737           36 :  cryst => db%cryst
    2738              : 
    2739              :  ! Generate q-mesh: find BZ, IBZ and the corresponding weights from ngqpt.
    2740           36 :  nq1 = ngqpt(1); nq2 = ngqpt(2); nq3 = ngqpt(3)
    2741           36 :  qptrlatt = 0; qptrlatt(1, 1) = ngqpt(1); qptrlatt(2, 2) = ngqpt(2); qptrlatt(3, 3) = ngqpt(3)
    2742              : 
    2743           36 :  ABI_CHECK(nqshift == 1, "nshift > 1 not supported")
    2744          144 :  ABI_CHECK(all(qshift(:, 1) == zero), "qshift != 0 not supported")
    2745              : 
    2746              :  call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, nqshift, qshift, &
    2747           36 :                              nqibz, qibz, wtq, nqbz, qbz) ! new_kptrlatt, new_shiftk)
    2748              : 
    2749          144 :  ABI_CHECK(nqbz == product(ngqpt) * nqshift, "nqbz /= product(ngqpt) * nqshift")
    2750              : 
    2751           72 :  select case (db%rspace_cell)
    2752              :  case (0)
    2753              :    ! Generate q-mesh
    2754              : #if 1
    2755           36 :    ABI_FREE(qbz)
    2756          108 :    ABI_MALLOC(qbz, (3, nqbz))
    2757           36 :    ii = 0
    2758          143 :    do iz=0,nq3-1
    2759          494 :      do iy=0,nq2-1
    2760         1699 :        do ix=0,nq1-1
    2761         1241 :          ii = ii + 1
    2762         4964 :          qbz(:, ii) = [ix / dble(nq1), iy / dble(nq2), iz / dble(nq3)]
    2763         5315 :          call wrap2_pmhalf([ix / dble(nq1), iy / dble(nq2), iz / dble(nq3)], qbz(:,ii), shift)
    2764              :        end do
    2765              :      end do
    2766              :    end do
    2767              : #endif
    2768              : 
    2769              :    ! Compute real-space points in the supercell
    2770              :    ! Use the following indexing (N means ngfft on the adequate direction)
    2771              :    ! 0 1 2 3 ... N/2    -(N-1)/2 ... -1    <= gc
    2772              :    ! 1 2 3 4 ....N/2+1  N/2+2    ...  N    <= index ig
    2773           36 :    nrtot = nqbz
    2774         5036 :    ABI_CALLOC(all_rpt, (3, nrtot))
    2775           36 :    ii = 0
    2776          143 :    do iz=1,nq3
    2777          107 :      r3 = ig2gfft(iz, nq3)
    2778          494 :      do iy=1,nq2
    2779          351 :        r2 = ig2gfft(iy, nq2)
    2780         1699 :        do ix=1,nq1
    2781         1241 :          r1 = ig2gfft(ix, nq1)
    2782         1241 :          ii = ii + 1
    2783         5315 :          all_rpt(:, ii) = [r1, r2, r3]
    2784              :        end do
    2785              :      end do
    2786              :    end do
    2787              : 
    2788              :  case (1)
    2789              :    ! Use Wigner-Seitz cell.
    2790              :    !
    2791              :    ! Compute rprim, and gprim
    2792            0 :    call mkradim(acell, rprim, cryst%rprimd)
    2793            0 :    call canat9(db%brav, cryst%natom, rcan, rprim, trans, cryst%xred)
    2794            0 :    call matr3inv(rprim, gprim)
    2795              : 
    2796              :    ! In principle one may have N_R that depends on iatom to minimize memory.
    2797              :    call get_bigbox_and_weights(db%brav, cryst%natom, nqbz, ngqpt, nqshift, qshift, rprim, cryst%rprimd, gprim, rcan, &
    2798            0 :                                cutmode2, nrtot, all_rcart, all_cell, all_wghatm, r_inscribed_sphere, comm)
    2799            0 :    ABI_FREE(all_cell)
    2800            0 :    do ii=1,nrtot
    2801            0 :      all_rcart(:,ii) = all_rcart(:,ii) * acell(:)
    2802              :    end do
    2803            0 :    ABI_MALLOC(all_rpt, (3, nrtot))
    2804            0 :    call xcart2xred(nrtot, cryst%rprimd, all_rcart, all_rpt)
    2805            0 :    ABI_FREE(all_rcart)
    2806              : 
    2807              :  case default
    2808           36 :    ABI_ERROR(sjoin("Wrong rspace_cell:", itoa(db%rspace_cell)))
    2809              :  end select
    2810              : 
    2811              :  ! Find correspondence BZ --> IBZ. Note:
    2812              :  !  - q --> -q symmetry is always used for phonons.
    2813              :  !  - we use symrec instead of symrel
    2814              : 
    2815          108 :  ABI_MALLOC(indqq, (6, nqbz))
    2816           36 :  call qrank%from_kptrlatt(nqibz, qibz, qptrlatt, compute_invrank=.False.)
    2817              : 
    2818           36 :  if (kpts_map("symrec", qptopt, cryst, qrank, nqbz, qbz, indqq) /= 0) then
    2819            0 :    ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map qBZ --> qIBZ")
    2820              :  end if
    2821              : 
    2822           36 :  call qrank%free()
    2823              : 
    2824              :  ! Construct sorted mapping BZ --> IBZ to speedup qbz search below.
    2825          108 :  ABI_MALLOC(iperm, (nqbz))
    2826           72 :  ABI_MALLOC(bz2ibz_sort, (nqbz))
    2827         3795 :  iperm = [(ii, ii=1,nqbz)]
    2828         1313 :  bz2ibz_sort = indqq(1, :)
    2829           36 :  call sort_int(nqbz, bz2ibz_sort, iperm)
    2830              : 
    2831              :  ! Reconstruct the IBZ according to what is present in the DVDB.
    2832          108 :  ABI_MALLOC(nqsts, (nqibz))
    2833           72 :  ABI_MALLOC(iqs_dvdb, (nqibz))
    2834          237 :  iqs_dvdb = -1
    2835              : 
    2836              :  iqst = 0
    2837          237 :  do iq_ibz=1,nqibz
    2838              :    ! In each q-point star, count the number of q-points and find the one present in the DVDB.
    2839          201 :    nqst = 0
    2840          201 :    found = .false.
    2841         1442 :    do ii=iqst+1,nqbz
    2842         1406 :      if (bz2ibz_sort(ii) /= iq_ibz) exit
    2843         1241 :      nqst = nqst + 1
    2844         1241 :      iq_bz = iperm(ii)
    2845         1442 :      if (.not. found) then
    2846          671 :        iq_dvdb = db%findq(qbz(:,iq_bz))
    2847          671 :        if (iq_dvdb /= -1) then
    2848          804 :          qibz(:,iq_ibz) = qbz(:,iq_bz)
    2849          201 :          iqs_dvdb(iq_ibz) = iq_dvdb
    2850          201 :          found = .true.
    2851              :        end if
    2852              :      end if
    2853              :    end do
    2854              : 
    2855              :    ! Check that nqst has been counted properly.
    2856          201 :    ABI_CHECK(nqst > 0 .and. bz2ibz_sort(iqst + 1) == iq_ibz, "Wrong iqst")
    2857          201 :    if (abs(nqst - wtq(iq_ibz) * nqbz) > tol12) then
    2858            0 :      write(msg, "(a,i0,a,f5.2)")"Error in q-point star or q-weights. nqst:", nqst, "wtq * nqbz = ", wtq(iq_ibz) * nqbz
    2859            0 :      ABI_ERROR(msg)
    2860              :    end if
    2861              : 
    2862              :    ! Check that the q-point has been found in DVDB.
    2863          201 :    ABI_CHECK(found, sjoin("Cannot find symmetric q-point of:", ktoa(qibz(:,iq_ibz)), "in DVDB file"))
    2864              : 
    2865          201 :    iqst = iqst + nqst
    2866          237 :    nqsts(iq_ibz) = nqst
    2867              :  end do
    2868              : 
    2869           36 :  ABI_FREE(wtq)
    2870           36 :  ABI_FREE(bz2ibz_sort)
    2871              : 
    2872              :  ! Redo the mapping with the new IBZ
    2873           36 :  call qrank%from_kptrlatt(nqibz, qibz, qptrlatt, compute_invrank=.False.)
    2874              : 
    2875           36 :  if (kpts_map("symrec", qptopt, cryst, qrank, nqbz, qbz, indqq) /= 0) then
    2876            0 :    ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map qBZ --> qIBZ")
    2877              :  end if
    2878           36 :  call qrank%free()
    2879              : 
    2880           36 : end subroutine prepare_ftinterp
    2881              : !!***
    2882              : 
    2883              : !----------------------------------------------------------------------
    2884              : 
    2885              : !!****f* m_dvdb/dvdb_ftinterp_qpt
    2886              : !! NAME
    2887              : !!  dvdb_ftinterp_qpt
    2888              : !!
    2889              : !! FUNCTION
    2890              : !!  Fourier interpolation of potentials for a given q-point
    2891              : !!  Internal tables must be prepared in advance by calling `dvdb_ftinterp_setup`.
    2892              : !!
    2893              : !!  \begin{equation}
    2894              : !!  \partial v^{scf}_{\tilde\qq\kappa\alpha}(\rr) \approx \sum_\RR e^{+i\tilde{\qq}\cdot(\RR - \rr)} W_{\kappa\alpha}(\rr,\RR).
    2895              : !!  \end{equation
    2896              : !!
    2897              : !! INPUTS
    2898              : !!  qpt(3)=q-point in reduced coordinates (arbitrary point in the BZ).
    2899              : !!  nfft=Number of FFT-points treated by this processors.
    2900              : !!  ngfft(18)=contain all needed information about 3D FFT.
    2901              : !!  comm=MPI communicator for R-points.
    2902              : !!  [add_lr]= If present, use this value for the LR treatment instead of dv%add_lr
    2903              : !!
    2904              : !! OUTPUT
    2905              : !!  ov1r(2*nfft, nspden, my_npert)=Interpolated DFPT potentials at the given q-point (periodic part)
    2906              : !!
    2907              : !! SOURCE
    2908              : 
    2909         3762 : subroutine dvdb_ftinterp_qpt(db, qpt, nfft, ngfft, ov1r, comm_rpt, add_lr)
    2910              : 
    2911              : !Arguments ------------------------------------
    2912              : !scalars
    2913              :  integer,intent(in) :: nfft, comm_rpt
    2914              :  integer,optional,intent(in) :: add_lr
    2915              :  class(dvdb_t),intent(inout) :: db
    2916              : !arrays
    2917              :  integer,intent(in) :: ngfft(18)
    2918              :  real(dp),intent(in) :: qpt(3)
    2919              :  real(dp),intent(out) :: ov1r(2, nfft, db%nspden, db%my_npert)
    2920              : 
    2921              : !Local variables-------------------------------
    2922              : !scalars
    2923              :  integer,parameter :: cplex2 = 2
    2924              :  integer :: ispden, imyp, idir, ipert, timerev_q, ierr, my_add_lr !, ifft, ir
    2925              :  !real(dp) :: qmod
    2926              :  !real(sp) :: beta_sp !, wr !,wi
    2927              :  logical :: prev_has_zeff, prev_has_quadrupoles, prev_has_efield
    2928              : !arrays
    2929         3762 :  integer :: symq(4,2,db%cryst%nsym), rfdir(3)
    2930         3762 :  integer,allocatable :: pertsy(:,:), rfpert(:), pflag(:,:)
    2931              :  !real(dp) :: qcart(3)
    2932         3762 :  real(dp),allocatable :: eiqr(:,:), v1r_lr(:,:,:)
    2933         3762 :  real(sp),allocatable :: weiqr_sp(:,:), ov1r_sp(:, :), eiqr_sp(:,:)
    2934              : ! *************************************************************************
    2935              : 
    2936         3762 :  my_add_lr = db%add_lr; if (present(add_lr)) my_add_lr = add_lr
    2937              : 
    2938              :  !qcart = two_pi * matmul(db%cryst%gprimd, qpt)
    2939              :  !qmod = sqrt(dot_product(qcart, qcart))
    2940              : 
    2941         3762 :  if (my_add_lr >= 4) then
    2942              :    ! Use LR part only and return immediately.
    2943            0 :    if (my_add_lr > 4) then
    2944            0 :      prev_has_zeff = db%has_zeff
    2945            0 :      prev_has_quadrupoles = db%has_quadrupoles
    2946            0 :      prev_has_efield = db%has_efield
    2947            0 :      db%has_zeff = .False.
    2948            0 :      db%has_quadrupoles = .False.
    2949            0 :      db%has_efield = .False.
    2950            0 :      if (my_add_lr == 5 .and. prev_has_zeff)  db%has_zeff = .True.
    2951            0 :      if (my_add_lr == 6 .and. prev_has_quadrupoles) db%has_quadrupoles = .True.
    2952            0 :      if (my_add_lr == 7 .and. prev_has_efield) db%has_efield = .True.
    2953              :    end if
    2954              : 
    2955            0 :    ov1r = zero
    2956            0 :    do imyp=1,db%my_npert
    2957            0 :      idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp)
    2958            0 :      call db%get_v1r_long_range(qpt, idir, ipert, nfft, ngfft, ov1r(:, :, 1, imyp))
    2959              :      ! Remove the phase to get the lattice-periodic part.
    2960            0 :      call times_eikr(-qpt, ngfft, nfft, 1, ov1r(:, :, 1, imyp))
    2961            0 :      if (db%nspden /= 1) ov1r(:, :, 2, imyp) = ov1r(:, :, 1, imyp)
    2962              :    end do
    2963              : 
    2964            0 :    if (my_add_lr > 4) then
    2965              :      ! Restore input flags.
    2966            0 :      db%has_zeff = prev_has_zeff
    2967            0 :      db%has_quadrupoles = prev_has_quadrupoles
    2968            0 :      db%has_efield = prev_has_efield
    2969              :    end if
    2970              : 
    2971            0 :    return
    2972              :  end if
    2973              : 
    2974         3762 :  ABI_CHECK(allocated(db%wsr), "wsr is not allocated (call dvdb_ftinterp_setup)")
    2975              : 
    2976              :  ! Examine the symmetries of the q-wavevector
    2977         3762 :  call littlegroup_q(db%cryst%nsym, qpt, symq, db%cryst%symrec, db%cryst%symafm, timerev_q, prtvol=db%prtvol)
    2978              : 
    2979              :  ! Compute long-range part of the coupling potential.
    2980         3762 :  if (my_add_lr > 0) then
    2981              :    !call wrtout(std_out, "dvdb_ftinterp_qpt: Computing long-range part of the coupling potential.")
    2982        10056 :    ABI_MALLOC(v1r_lr, (2, nfft, db%my_npert))
    2983        17598 :    do imyp=1,db%my_npert
    2984        15084 :      idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp)
    2985        17598 :      call db%get_v1r_long_range(qpt, idir, ipert, nfft, ngfft, v1r_lr(:,:,imyp))
    2986              :    end do
    2987              :  end if
    2988              : 
    2989              :  ! Compute e^{iq.R} FT phases for this q-point.
    2990        11286 :  ABI_MALLOC(eiqr, (2, db%my_nrpt))
    2991         3762 :  call calc_eiqr(qpt, db%my_nrpt, db%my_rpt, eiqr)
    2992              : 
    2993              :  ! Interpolate potentials (results in ov1r)
    2994         3762 :  if (db%nprocs_rpt > 1) ov1r = zero
    2995        11286 :  ABI_MALLOC(ov1r_sp, (2, nfft))
    2996              : 
    2997        11286 :  ABI_MALLOC(weiqr_sp, (db%my_nrpt, 2))
    2998         7524 :  ABI_MALLOC(eiqr_sp, (db%my_nrpt, 2))
    2999       275908 :  eiqr_sp = transpose(eiqr)
    3000              : 
    3001        23778 :  do imyp=1,db%my_npert
    3002        20016 :    idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp)
    3003              : 
    3004       782148 :    weiqr_sp(:, 1) = db%my_wratm(:, ipert) * eiqr_sp(:, 1)
    3005       782148 :    weiqr_sp(:, 2) = db%my_wratm(:, ipert) * eiqr_sp(:, 2)
    3006              : 
    3007        40032 :    do ispden=1,db%nspden
    3008              : 
    3009              :      ! We need to compute: sum_R W(R, r) e^{iq.R} with W real matrix.
    3010              :      ! Use BLAS2 to compute ov1r = W (x + iy) but need to handle kind conversion as ov1r is double-precision
    3011              :      ! NB: Can use MKL BLAS-like extensions to perform 2 matrix-vector operations:
    3012              :      !   call dgem2vu(m, n, alpha, a, lda, x1, incx1, x2, incx2, beta, y1, incy1, y2, incy2)
    3013              :      ! unfortunately the API does not support transa so one has to transport db%wsr.
    3014              :      ! Alternatively, compute all my_npert with ZGEMM (more memory but it should be more efficient).
    3015              : 
    3016              :      !select case (db%gpu_option)
    3017              :      !case (ABI_GPU_DISABLED)
    3018              :        call SGEMV("T", db%my_nrpt, nfft, one_sp, db%wsr(1,1,1,ispden,imyp), db%my_nrpt, weiqr_sp(1,1), 1, &
    3019        20016 :                   zero_sp, ov1r_sp(1,1), 2)
    3020              :        call SGEMV("T", db%my_nrpt, nfft, one_sp, db%wsr(1,1,1,ispden,imyp), db%my_nrpt, weiqr_sp(1,2), 1, &
    3021        20016 :                   zero_sp, ov1r_sp(2,1), 2)
    3022              :      !case (ABI_GPU_OPENMP)
    3023              :        ! TODO
    3024              :      !case default
    3025              :      !  ABI_ERROR(sjoin("ftinterp_qpt: unsupported gpu_option:", itoa(db%gpu_option)))
    3026              :      !end select
    3027              : 
    3028    406968624 :      ov1r(:, :, ispden, imyp) = ov1r_sp(:, :)
    3029              : 
    3030              :      ! Add the long-range part of the potential
    3031        20016 :      if (my_add_lr > 0) then
    3032              :        !call wrtout(std_out, "Adding the long-range part of the potential")
    3033    164629692 :        ov1r(:, :, ispden, imyp) = ov1r(:, :, ispden, imyp) + v1r_lr(:, :, imyp)
    3034              :      end if
    3035              : 
    3036              :      ! Remove the phase to get the lattice-periodic part.
    3037        80064 :      call times_eikr(-qpt, ngfft, nfft, 1, ov1r(:, :, ispden, imyp))
    3038              : 
    3039              :      ! Need to collect results if R-points are distributed (TODO Non-blocking API?)
    3040        40032 :      if (db%nprocs_rpt > 1) call xmpi_sum(ov1r(:,:,ispden,imyp), comm_rpt, ierr)
    3041              :    end do ! ispden
    3042              : 
    3043              :    ! Be careful with Gamma-point and cplex!
    3044        23778 :    if (db%symv1 == 1) then !(.and. receiver == -1 .or. receiver == db%comm_rpt%my_rank)
    3045              :      call v1phq_symmetrize(db%cryst, idir, ipert, symq, ngfft, cplex2, nfft, db%nspden, db%nsppol, &
    3046         1218 :                            db%mpi_enreg, ov1r(:,:,:,imyp))
    3047              :    end if
    3048              :  end do ! imyp
    3049              : 
    3050         3762 :  ABI_FREE(ov1r_sp)
    3051              : 
    3052         3762 :  if (db%symv1 == 2) then
    3053              :    ! Symmetrize potentials (this part is seldom executed)
    3054              :    ! Initialize the list of perturbations rfpert and rdfir
    3055              :    ! WARNING: Only phonon perturbations are considered for the time being.
    3056            0 :    ABI_MALLOC(rfpert, (db%mpert))
    3057            0 :    rfpert = 0; rfpert(1:db%cryst%natom) = 1; rfdir = 1
    3058            0 :    ABI_MALLOC(pertsy, (3, db%mpert))
    3059            0 :    ABI_MALLOC(pflag, (3, db%natom))
    3060              : 
    3061              :    ! Determine the symmetrical perturbations. Meaning of pertsy:
    3062              :    !    0 for non-target perturbations
    3063              :    !    1 for basis perturbations
    3064              :    !   -1 for perturbations that can be found from basis perturbations
    3065              :    call irreducible_set_pert(db%cryst%indsym,db%mpert,db%cryst%natom,db%cryst%nsym,&
    3066            0 :        pertsy,rfdir,rfpert,symq,db%cryst%symrec,db%cryst%symrel)
    3067              : 
    3068            0 :    pflag = 0
    3069            0 :    do imyp=1,3*db%cryst%natom
    3070            0 :      idir = mod(imyp-1, 3) + 1; ipert = (imyp - idir) / 3 + 1
    3071            0 :      if (pertsy(idir, ipert) == 1) pflag(idir,ipert) = 1
    3072              :    end do
    3073              : 
    3074              :    ! Complete potentials
    3075            0 :    call v1phq_complete(db%cryst,qpt,ngfft,cplex2,nfft,db%nspden,db%nsppol,db%mpi_enreg,db%symv1,pflag,ov1r)
    3076              : 
    3077            0 :    ABI_FREE(pertsy)
    3078            0 :    ABI_FREE(rfpert)
    3079            0 :    ABI_FREE(pflag)
    3080              :  endif
    3081              : 
    3082              :  ! Set imaginary part to zero if gamma point.
    3083      6133032 :  if (sum(qpt**2) < tol14) ov1r(2, :, :, :) = zero
    3084              : 
    3085         3762 :  ABI_FREE(eiqr)
    3086         3762 :  ABI_FREE(weiqr_sp)
    3087         3762 :  ABI_SFREE(v1r_lr)
    3088         3762 :  ABI_SFREE(eiqr_sp)
    3089              : 
    3090         3762 : end subroutine dvdb_ftinterp_qpt
    3091              : !!***
    3092              : 
    3093              : !----------------------------------------------------------------------
    3094              : 
    3095              : !!****f* m_dvdb/dvdb_get_ftqbz
    3096              : !! NAME
    3097              : !!  dvdb_get_ftqbz
    3098              : !!
    3099              : !! FUNCTION
    3100              : !!  Fourier interpolation of potentials for a given q-point in the BZ (qbz).
    3101              : !!  Internal tables must be prepared in advance by calling `dvdb_ftinterp_setup`.
    3102              : !!
    3103              : !! INPUTS
    3104              : !!  qbz(3)= q-point in the BZ in reduced coordinates.
    3105              : !!  nfft=Number of fft-points treated by this processors
    3106              : !!  ngfft(18)=contain all needed information about 3D FFT
    3107              : !!
    3108              : !! OUTPUT
    3109              : !!  ov1r(2*nfft, nspden, my_npert)=Interpolated DFPT potentials at the given q-point.
    3110              : !!
    3111              : !! SOURCE
    3112              : 
    3113         3757 : subroutine dvdb_get_ftqbz(db, qbz, cplex, nfft, ngfft, v1scf, comm)
    3114              : 
    3115              : !Arguments ------------------------------------
    3116              : !scalars
    3117              :  class(dvdb_t),intent(inout) :: db
    3118              :  integer,intent(in) :: nfft, comm
    3119              :  integer,intent(out) :: cplex
    3120              : !arrays
    3121              :  integer,intent(in) :: ngfft(18)
    3122              :  real(dp),intent(in) :: qbz(3)
    3123              :  real(dp),allocatable,intent(out) :: v1scf(:,:,:,:)
    3124              : 
    3125              : !Local variables-------------------------------
    3126              :  real(dp) :: tsec(2)
    3127              : ! *************************************************************************
    3128              : 
    3129              :  ABI_UNUSED(comm)
    3130              : 
    3131              :  ! Keep track of total time spent.
    3132         3757 :  call timab(1809, 1, tsec)
    3133              : 
    3134              :  ! Interpolate the dvscf potentials directly in the **BZ** for my_npert perturbations.
    3135              :  ! This is possible only if all procs inside comm_rpt call this routine else deadlock
    3136              :  ! Note that cplex is always set to 2 here
    3137         3757 :  cplex = 2
    3138        18785 :  ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert))
    3139         3757 :  call db%ftinterp_qpt(qbz, nfft, ngfft, v1scf, db%comm_rpt)
    3140         3757 :  call timab(1809, 2, tsec)
    3141              : 
    3142         3757 : end subroutine dvdb_get_ftqbz
    3143              : !!***
    3144              : 
    3145              : !----------------------------------------------------------------------
    3146              : 
    3147              : !!****f* m_dvdb/dvdb_get_vxc1_ftqbz
    3148              : !! NAME
    3149              : !!  dvdb_get_vxc1_ftqbz
    3150              : !!
    3151              : !! FUNCTION
    3152              : !! Fourier interpolation of the first-order change of exchange-correlation potential
    3153              : !! for a given q-point in the BZ (qbz).
    3154              : !!
    3155              : !! INPUTS
    3156              : !!  cryst<crystal_t>=crystal structure parameters
    3157              : !!  dtset<dataset_type>=All input variables for this dataset
    3158              : !!  qbz(3)=Q-point in BZ
    3159              : !!  nfft=Number of fft-points treated by this processors
    3160              : !!  ngfft(18)=contain all needed information about 3D FFT
    3161              : !!  nkxc=second dimension of the array kxc, see rhohxc.f for a description
    3162              : !!  kxc(nfftf,nkxc)=second derivative of the exchange-correlation functional
    3163              : !!  non_magnetic_xc=true if density/potential is handled as non-magnetic
    3164              : !!  usexcnhat=0, the exchange-correlation potential does not include the compensation charge density
    3165              : !!  comm=MPI communicator (either xmpi_comm_self or comm for perturbations
    3166              : !!
    3167              : !! OUTPUT
    3168              : !!  drho_cplex=1 if real, 2 if complex.
    3169              : !!  vxc1(drho_cplex, nfft, nspden, db%my_npert)= vxc1 potentials on the real-space FFT mesh
    3170              : !!  for the db%my_npert perturbations treated by this MPI rank.
    3171              : !!
    3172              : !! SOURCE
    3173              : 
    3174            0 : subroutine dvdb_get_vxc1_ftqbz(db, dtset, cryst, qbz, drho_cplex, nfft, ngfft, nkxc, kxc, &
    3175              :                                vxc1, non_magnetic_xc, usexcnhat, comm)
    3176              : 
    3177              : !Arguments ------------------------------------
    3178              : !scalars
    3179              :  class(dvdb_t),intent(inout) :: db
    3180              :  integer,intent(in) :: nfft, nkxc, usexcnhat, comm
    3181              :  integer,intent(out) :: drho_cplex
    3182              :  real(dp),intent(in) :: qbz(3)
    3183              :  type(dataset_type),intent(in) :: dtset
    3184              :  type(crystal_t),intent(in) :: cryst
    3185              :  logical,intent(in) :: non_magnetic_xc
    3186              : !arrays
    3187              :  integer,intent(in) :: ngfft(18)
    3188              :  real(dp),intent(in) :: kxc(nfft,nkxc)
    3189              :  real(dp),allocatable,intent(out) :: vxc1(:,:,:,:)
    3190              : 
    3191              : !Local variables-------------------------------
    3192              : !scalars
    3193              :  integer :: option,imyp
    3194              : !arrays
    3195            0 :  real(dp),allocatable :: rho1(:,:,:,:)
    3196              :  real(dp) :: dum_nhat(0), dum_xccc3d1(0)
    3197              : ! *************************************************************************
    3198              : 
    3199              :  ! Get rho1(cplex, nfftf, nspden, my_npert))
    3200            0 :  call db%get_ftqbz(qbz, drho_cplex, nfft, ngfft, rho1, comm)
    3201              : 
    3202            0 :  option = 2  ! if 2, treat only density change
    3203              :  !option = 1 ! if 1, treat both density change and XC core correction
    3204            0 :  ABI_MALLOC(vxc1, (drho_cplex, nfft, dtset%nspden, db%my_npert))
    3205              : 
    3206            0 :  do imyp=1,db%my_npert
    3207              :    call dfpt_mkvxc(drho_cplex,dtset%ixc,kxc,db%mpi_enreg,nfft,ngfft,dum_nhat,0,dum_nhat,0,&
    3208              :                    nkxc,non_magnetic_xc,dtset%nspden,0,option,qbz,rho1(:,:,:,imyp),&
    3209            0 :                    cryst%rprimd,usexcnhat,vxc1(:,:,:,imyp),dum_xccc3d1)
    3210              :  end do
    3211              : 
    3212            0 :  ABI_FREE(rho1)
    3213              : 
    3214            0 : end subroutine dvdb_get_vxc1_ftqbz
    3215              : !!***
    3216              : 
    3217              : !----------------------------------------------------------------------
    3218              : 
    3219              : !!****f* m_dvdb/dvdb_get_v1scf_rpt
    3220              : !! NAME
    3221              : !!  dvdb_get_v1scf_rpt
    3222              : !!
    3223              : !! FUNCTION
    3224              : !!  Compute the phonon perturbation potential in real space lattice representation.
    3225              : !!  This routine is meant to replace dvdb_ftinterp_setup
    3226              : !!  and performs the potential interpolation one perturbation at a time.
    3227              : !!
    3228              : !! INPUTS
    3229              : !!  ngqpt(3)=Divisions of the ab-initio q-mesh.
    3230              : !!  nqshift=Number of shifts used to generated the ab-initio q-mesh.
    3231              : !!  qshift(3,nqshift)=The shifts of the ab-initio q-mesh.
    3232              : !!  nfft=Number of fft-points treated by this processors
    3233              : !!  ngfft(18)=contain all needed information about 3D FFT
    3234              : !!  nrpt=Number of R-points = number of q-points in the full BZ
    3235              : !!  nspden=Number of spin densities.
    3236              : !!  ipert=index of the perturbation to be treated [1,natom3]
    3237              : !!  comm=MPI communicator
    3238              : !!
    3239              : !! OUTPUT
    3240              : !!  v1scf_rpt(2,nrpt,nfft,nspden)
    3241              : !!
    3242              : !! SOURCE
    3243              : 
    3244           31 : subroutine dvdb_get_v1scf_rpt(db, cryst, ngqpt, nqshift, qshift, nfft, ngfft, &
    3245           31 :                               nrpt, nspden, ipert, v1scf_rpt, comm)
    3246              : 
    3247              : !Arguments ------------------------------------
    3248              : !scalars
    3249              :  integer,intent(in) :: nqshift,nfft,nrpt,nspden,ipert,comm
    3250              :  class(dvdb_t),target,intent(inout) :: db
    3251              : !arrays
    3252              :  integer,intent(in) :: ngqpt(3),ngfft(18)
    3253              :  real(dp),intent(in) :: qshift(3,nqshift)
    3254              :  real(dp),intent(out) :: v1scf_rpt(2,nrpt,nfft,nspden)
    3255              :  type(crystal_t),intent(in) :: cryst
    3256              : 
    3257              : !Local variables-------------------------------
    3258              : !scalars
    3259              :  integer,parameter :: sppoldbl1=1, timrev1=1
    3260              :  integer :: my_qptopt,iq_ibz,nqibz,iq_bz,nqbz
    3261              :  integer :: ii,iq_dvdb,cplex_qibz,ispden,irpt,idir,iat
    3262              :  integer :: iqst,nqst,itimrev,tsign,isym,ix,iy,iz,nq1,nq2,nq3,r1,r2,r3
    3263              :  integer :: nproc,my_rank,ifft,cnt,ierr
    3264              :  character(len=500) :: msg
    3265              :  real(dp) :: dksqmax, cpu, wall, gflops
    3266              :  logical :: isirr_q, found
    3267              : !arrays
    3268              :  integer :: qptrlatt(3,3),g0q(3)
    3269           31 :  integer,allocatable :: indqq(:,:),iperm(:),bz2ibz_sort(:),nqsts(:),iqs_dvdb(:)
    3270              :  real(dp) :: qpt_bz(3),shift(3)
    3271           31 :  real(dp),allocatable :: qibz(:,:),qbz(:,:),wtq(:),emiqr(:,:)
    3272           31 :  real(dp),allocatable :: v1r_qibz(:,:,:,:),v1r_qbz(:,:,:,:), v1r_lr(:,:)
    3273              : ! *************************************************************************
    3274              : 
    3275              :  !ABI_ERROR("Legacy code!")
    3276              : 
    3277           31 :  nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    3278              : 
    3279           31 :  nq1 = ngqpt(1); nq2 = ngqpt(2); nq3 = ngqpt(3); my_qptopt = 1 !; if (present(qptopt)) my_qptopt = qptopt
    3280              : 
    3281              :  ! Generate the q-mesh by finding the IBZ and the corresponding weights.
    3282           31 :  qptrlatt = 0
    3283          124 :  do ii=1,3
    3284          124 :    qptrlatt(ii,ii) = ngqpt(ii)
    3285              :  end do
    3286              : 
    3287              :  ! Get IBZ and BZ.
    3288              :  call kpts_ibz_from_kptrlatt(cryst, qptrlatt, my_qptopt, nqshift, qshift, &
    3289           31 :    nqibz, qibz, wtq, nqbz, qbz) ! new_kptrlatt, new_shiftk)
    3290              : 
    3291              :  !write(std_out,*)"Irreducible q-points:"
    3292              :  !do iq_ibz=1,nqibz; write(std_out,*)trim(ktoa(qibz(:,iq_ibz))),wtq(iq_ibz)*nqbz; end do
    3293          124 :  ABI_CHECK(nqbz == product(ngqpt) * nqshift, "nqbz /= product(ngqpt) * nqshift")
    3294           31 :  ABI_CHECK(nqbz == nrpt, "nqbz /= nrpt")
    3295              : 
    3296           31 :  db%my_nrpt = nqbz
    3297              : 
    3298           31 :  ABI_CHECK(nspden == db%nspden, "nspden /= db%nspden")
    3299              : 
    3300              :  ! We want a gamma centered q-mesh for FFT.
    3301           31 :  ABI_CHECK(nqshift == 1, "nshift > 1 not supported")
    3302          124 :  ABI_CHECK(all(qshift(:,1) == zero), "qshift != 0 not supported")
    3303              : 
    3304           31 :  ABI_FREE(qbz)
    3305           93 :  ABI_MALLOC(qbz, (3, nqbz))
    3306           31 :  ii = 0
    3307           99 :  do iz=0,nq3-1
    3308          259 :    do iy=0,nq2-1
    3309          644 :      do ix=0,nq1-1
    3310          416 :        ii = ii + 1
    3311         1664 :        qbz(:, ii) = [ix/dble(nq1), iy/dble(nq2), iz/dble(nq3)]
    3312         1824 :        call wrap2_pmhalf([ix/dble(nq1), iy/dble(nq2), iz/dble(nq3)], qbz(:,ii), shift)
    3313              :      end do
    3314              :    end do
    3315              :  end do
    3316              : 
    3317              :  ! Compute real-space points.
    3318              :  ! Use the following indexing (N means ngfft of the adequate direction)
    3319              :  ! 0 1 2 3 ... N/2    -(N-1)/2 ... -1    <= gc
    3320              :  ! 1 2 3 4 ....N/2+1  N/2+2    ...  N    <= index ig
    3321           93 :  ABI_MALLOC(db%my_rpt, (3, db%my_nrpt))
    3322           31 :  ii = 0
    3323           99 :  do iz=1,nq3
    3324           68 :    r3 = ig2gfft(iz,nq3)
    3325          259 :    do iy=1,nq2
    3326          160 :      r2 = ig2gfft(iy,nq2)
    3327          644 :      do ix=1,nq1
    3328          416 :        r1 = ig2gfft(ix,nq1)
    3329          416 :        ii = ii + 1
    3330         1824 :        db%my_rpt(:,ii) = [r1, r2, r3]
    3331              :      end do
    3332              :    end do
    3333              :  end do
    3334              : 
    3335              :  ! Find correspondence BZ --> IBZ. Note:
    3336              :  ! q --> -q symmetry is always used for phonons.
    3337              :  ! we use symrec instead of symrel
    3338           93 :  ABI_MALLOC(indqq, (nqbz*sppoldbl1,6))
    3339              :  call listkk(dksqmax,cryst%gmet,indqq,qibz,qbz,nqibz,nqbz,cryst%nsym,&
    3340           31 :              sppoldbl1,cryst%symafm,cryst%symrec,timrev1,comm,use_symrec=.True.)
    3341              : 
    3342              :  !call qrank%from_kptrlatt(new%nqibz, new%qibz, qptrlatt, compute_invrank=.False.)
    3343              :  !call qrank%get_mapping(new%nqbz, new%qbz, dksqmax, cryst%gmet, temp, &
    3344              :  !                       cryst%nsym, cryst%symafm, cryst%symrec, 1, use_symrec=.True.)
    3345              :  !call qrank%free()
    3346              : 
    3347           31 :  if (dksqmax > tol12) then
    3348            0 :    ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map BZ --> IBZ")
    3349              :  end if
    3350              : 
    3351              :  ! Construct sorted mapping BZ --> IBZ to speedup qbz search below.
    3352           93 :  ABI_MALLOC(iperm, (nqbz))
    3353           62 :  ABI_MALLOC(bz2ibz_sort, (nqbz))
    3354         1310 :  iperm = [(ii, ii=1,nqbz)]
    3355          478 :  bz2ibz_sort = indqq(:,1)
    3356           31 :  call sort_int(nqbz, bz2ibz_sort, iperm)
    3357              : 
    3358              :  ! Reconstruct the IBZ according to what is present in the DVDB.
    3359           93 :  ABI_MALLOC(nqsts, (nqibz))
    3360           62 :  ABI_MALLOC(iqs_dvdb, (nqibz))
    3361           93 :  ABI_MALLOC(v1r_lr, (2,nfft))
    3362              : 
    3363           31 :  iqst = 0
    3364          139 :  do iq_ibz=1,nqibz
    3365              :    ! In each q-point star, count the number of q-points and find the one present in DVDB.
    3366          108 :    nqst = 0
    3367          108 :    found = .false.
    3368          524 :    do ii=iqst+1,nqbz
    3369          493 :      if (bz2ibz_sort(ii) /= iq_ibz) exit
    3370          416 :      nqst = nqst + 1
    3371              : 
    3372          416 :      iq_bz = iperm(ii)
    3373          524 :      if (.not. found) then
    3374          317 :        iq_dvdb = db%findq(qbz(:,iq_bz))
    3375          317 :        if (iq_dvdb /= -1) then
    3376          432 :          qibz(:,iq_ibz) = qbz(:,iq_bz)
    3377          108 :          iqs_dvdb(iq_ibz) = iq_dvdb
    3378          108 :          found = .true.
    3379              :        end if
    3380              :      end if
    3381              :    end do
    3382              : 
    3383              :    ! Check that nqst has been counted properly.
    3384          108 :    ABI_CHECK(nqst > 0 .and. bz2ibz_sort(iqst+1) == iq_ibz, "Wrong iqst")
    3385          108 :    if (abs(nqst - wtq(iq_ibz) * nqbz) > tol12) then
    3386            0 :      write(std_out,*)nqst, wtq(iq_ibz) * nqbz
    3387            0 :      ABI_ERROR("Error in counting q-point star or in the weights.")
    3388              :    end if
    3389              : 
    3390              :    ! Check that the q-point has been found in DVDB.
    3391          108 :    if (.not. found) then
    3392            0 :      ABI_ERROR(sjoin("Cannot find symmetric q-point of:", ktoa(qibz(:,iq_ibz)), "in DVDB file"))
    3393              :    end if
    3394              :    !write(std_out,*)sjoin("qpt irred:",ktoa(qibz(:,iq_ibz)))
    3395              : 
    3396          108 :    iqst = iqst + nqst
    3397          139 :    nqsts(iq_ibz) = nqst
    3398              :  end do
    3399              : 
    3400              :  ! Redo the mapping with the new IBZ
    3401              :  call listkk(dksqmax,cryst%gmet,indqq,qibz,qbz,nqibz,nqbz,cryst%nsym,&
    3402           31 :              sppoldbl1,cryst%symafm,cryst%symrec,timrev1,comm,use_symrec=.True.)
    3403              : 
    3404              :  !call qrank%from_kptrlatt(new%nqibz, new%qibz, qptrlatt, compute_invrank=.False.)
    3405              :  !call qrank%get_mapping(new%nqbz, new%qbz, dksqmax, cryst%gmet, temp, &
    3406              :  !                       cryst%nsym, cryst%symafm, cryst%symrec, 1, use_symrec=.True.)
    3407              :  !call qrank%free()
    3408              : 
    3409           31 :  if (dksqmax > tol12) then
    3410            0 :    ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map BZ --> IBZ")
    3411              :  end if
    3412              : 
    3413           93 :  ABI_MALLOC(emiqr, (2, db%my_nrpt))
    3414     11230149 :  v1scf_rpt = zero
    3415              : 
    3416          155 :  ABI_MALLOC_OR_DIE(v1r_qbz, (2, nfft, db%nspden, db%natom3), ierr)
    3417              :  !v1r_qbz = huge(one)
    3418              : 
    3419           31 :  iqst = 0
    3420           31 :  call cwtime(cpu, wall, gflops, "start")
    3421          139 :  do iq_ibz=1,nqibz
    3422              : 
    3423              :    ! Get potentials for this IBZ q-point on the real-space FFT mesh.
    3424              :    ! This call allocates v1r_qibz(cplex_qibz, nfft, nspden, 3*natom)
    3425          108 :    call db%readsym_allv1(iqs_dvdb(iq_ibz), cplex_qibz, nfft, ngfft, v1r_qibz, comm)
    3426              : 
    3427              :    ! Reconstruct by symmetry the potentials for the star of this q-point, perform FT and accumulate
    3428              :    ! Be careful with the gamma point.
    3429          524 :    do ii=1,nqsts(iq_ibz)
    3430          416 :      iqst = iqst + 1
    3431          416 :      iq_bz = iperm(iqst)
    3432          416 :      ABI_CHECK(iq_ibz == indqq(iq_bz,1), "iq_ibz !/ ind qq(1)")
    3433         1664 :      isym = indqq(iq_bz,2); itimrev = indqq(iq_bz,6) + 1; g0q = indqq(iq_bz,3:5) ! IS(q_ibz) + g0q = q_bz
    3434          416 :      tsign = 3-2*itimrev
    3435              : 
    3436         1664 :      qpt_bz = qbz(:, iq_bz)
    3437              :      !write(std_out,*)"  treating:",trim(ktoa(qpt_bz))
    3438         1681 :      isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0))
    3439              :      !ABI_CHECK(all(g0q == 0), "g0q /= 0")
    3440              : 
    3441              :      ! Compute long-range part of the coupling potential
    3442              :      !call cwtime(cpu, wall, gflops, "start")
    3443     10816136 :      v1r_lr = zero; cnt = 0
    3444          416 :      if (db%add_lr /= 0) then
    3445          128 :        idir = mod(ipert-1, 3) + 1; iat = (ipert - idir) / 3 + 1
    3446          128 :        call db%get_v1r_long_range(qpt_bz, idir, iat, nfft, ngfft, v1r_lr)
    3447              :      end if
    3448              :      !call cwtime_report(" dvdb_get_v1r_long_range", cpu, wall, gflops)
    3449              : 
    3450          524 :      if (cplex_qibz == 1) then
    3451              :        ! Gamma point.
    3452           31 :        ABI_CHECK(nqsts(iq_ibz) == 1, "cplex_qibz == 1 and nq nqst /= 1 (should be gamma)")
    3453          124 :        ABI_CHECK(all(g0q == 0), "gamma point with g0q /= 0")
    3454              : 
    3455              :        ! Subtract the long-range part of the potential
    3456           31 :        if (db%add_lr /= 0) then
    3457           32 :          do ispden=1,db%nspden
    3458       159090 :            v1r_qibz(1,:,ispden,ipert) = v1r_qibz(1,:,ispden,ipert) - v1r_lr(1,:)
    3459              :          end do
    3460              :        end if
    3461              : 
    3462              :        ! SLOW FT.
    3463              :        !call cwtime(cpu, wall, gflops, "start")
    3464           31 :        cnt = 0
    3465           62 :        do ispden=1,db%nspden
    3466          478 :          do irpt=1,db%my_nrpt
    3467              :            ! MPI-parallelism
    3468          416 :            cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle
    3469      3605687 :            do ifft=1,nfft
    3470              :              v1scf_rpt(1,irpt,ifft,ispden) = v1scf_rpt(1,irpt,ifft,ispden) + &
    3471      3605656 :                                              v1r_qibz(1, ifft, ispden, ipert)
    3472              :            end do
    3473              :          end do
    3474              :        end do
    3475              :        !call cwtime_report(" slow fft", cpu, wall, gflops)
    3476              : 
    3477              :      else
    3478              :        ! q /= Gamma
    3479              :        ! Get the periodic part of the potential in BZ (v1r_qbz)
    3480          385 :        if (isirr_q) then
    3481              :          !write(std_out,*)sjoin("qpt irred:",ktoa(qpt_bz))
    3482     15058132 :          v1r_qbz = v1r_qibz
    3483              :        else
    3484              :          !call cwtime(cpu, wall, gflops, "start")
    3485              :          call v1phq_rotate(cryst, qibz(:,iq_ibz), isym, itimrev, g0q, &
    3486          308 :                            ngfft, cplex_qibz, nfft, db%nspden, db%mpi_enreg, v1r_qibz, v1r_qbz, xmpi_comm_self)
    3487              :        end if
    3488              : 
    3489              :        ! Multiply by e^{iqpt_bz.r}
    3490          385 :        call times_eikr(qpt_bz, ngfft, nfft, db%nspden*db%natom3, v1r_qbz)
    3491              : 
    3492              :        ! Subtract the long-range part of the potential
    3493          385 :        if (db%add_lr /= 0) then
    3494          224 :          do ispden=1,db%nspden
    3495      1113518 :            v1r_qbz(1,:,ispden,ipert) = v1r_qbz(1,:,ispden,ipert) - v1r_lr(1,:)
    3496      1113630 :            v1r_qbz(2,:,ispden,ipert) = v1r_qbz(2,:,ispden,ipert) - v1r_lr(2,:)
    3497              :          end do
    3498              :        end if
    3499              : 
    3500              :        ! Compute FT phases for this qpt_bz.
    3501         1540 :        call calc_eiqr(-qpt_bz, db%my_nrpt, db%my_rpt, emiqr)
    3502              : 
    3503              :        ! SLOW FT.
    3504              :        !call cwtime_report(" phases", cpu, wall, gflops)
    3505          385 :        cnt = 0
    3506          770 :        do ispden=1,db%nspden
    3507      3191643 :          do ifft=1,nfft
    3508      3190873 :            cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
    3509              : 
    3510              :            v1scf_rpt(1,:,ifft,ispden) = v1scf_rpt(1,:,ifft,ispden) &
    3511              :                                    + emiqr(1,:) * v1r_qbz(1, ifft, ispden, ipert) &
    3512     47007009 :                                    - emiqr(2,:) * v1r_qbz(2, ifft, ispden, ipert)
    3513              : 
    3514              :            v1scf_rpt(2,:,ifft,ispden) = v1scf_rpt(2,:,ifft,ispden) &
    3515              :                                    + emiqr(1,:) * v1r_qbz(2, ifft, ispden, ipert) &
    3516     47007394 :                                    + emiqr(2,:) * v1r_qbz(1, ifft, ispden, ipert)
    3517              :          end do
    3518              :        end do
    3519              :        !call cwtime_report(" slow fft", cpu, wall, gflops)
    3520              :      end if
    3521              : 
    3522              :    end do ! iqst
    3523              : 
    3524          108 :    write(msg,'(2(a,i0),a)') " q-point [",iq_ibz,"/",nqibz,"]"
    3525          108 :    call cwtime_report(msg, cpu, wall, gflops)
    3526              : 
    3527          139 :    ABI_FREE(v1r_qibz)
    3528              :  end do ! iq_ibz
    3529           31 :  ABI_CHECK(iqst == nqbz, "iqst /= nqbz")
    3530              : 
    3531     11230149 :  v1scf_rpt = v1scf_rpt / nqbz
    3532           31 :  call xmpi_sum(v1scf_rpt, comm, ierr)
    3533              : 
    3534           31 :  ABI_FREE(emiqr)
    3535           31 :  ABI_FREE(qibz)
    3536           31 :  ABI_FREE(wtq)
    3537           31 :  ABI_FREE(qbz)
    3538           31 :  ABI_FREE(indqq)
    3539           31 :  ABI_FREE(iperm)
    3540           31 :  ABI_FREE(bz2ibz_sort)
    3541           31 :  ABI_FREE(iqs_dvdb)
    3542           31 :  ABI_FREE(nqsts)
    3543           31 :  ABI_FREE(v1r_qbz)
    3544           31 :  ABI_FREE(v1r_lr)
    3545              : 
    3546           62 : end subroutine dvdb_get_v1scf_rpt
    3547              : !!***
    3548              : 
    3549              : !----------------------------------------------------------------------
    3550              : 
    3551              : !!****f* m_dvdb/dvdb_get_v1scf_qpt
    3552              : !! NAME
    3553              : !!  dvdb_get_v1scf_qpt
    3554              : !!
    3555              : !! FUNCTION
    3556              : !!  Fourier interpolation of potentials for a given q-point
    3557              : !!  This routine is meant to replace dvdb_ftinterp_qpt
    3558              : !!  by performing the interpolation one perturbation at a time.
    3559              : !!
    3560              : !! INPUTS
    3561              : !!  qpt(3)=q-point in reduced coordinates.
    3562              : !!  nfft=Number of fft-points treated by this processors
    3563              : !!  ngfft(18)=contain all needed information about 3D FFT
    3564              : !!  nrpt=Number of R-points = number of q-points in the full BZ
    3565              : !!  nspden=Number of spin densities.
    3566              : !!  ipert=index of the perturbation to be treated [1,natom3]
    3567              : !!  v1scf_rpt(2,nrpt,nfft,nspden)=phonon perturbation potential in real space lattice representation.
    3568              : !!  comm=MPI communicator
    3569              : !!
    3570              : !! OUTPUT
    3571              : !!  v1scf_qpt(2*nfft, nspden)=Interpolated DFPT potentials at the given q-point.
    3572              : !!
    3573              : !! SOURCE
    3574              : 
    3575          244 : subroutine dvdb_get_v1scf_qpt(db, cryst, qpt, nfft, ngfft, nrpt, nspden, &
    3576          244 :                               ipert, v1scf_rpt, v1scf_qpt, comm)
    3577              : 
    3578              : !Arguments ------------------------------------
    3579              : !scalars
    3580              :  integer,intent(in) :: nfft,nrpt,nspden,ipert,comm
    3581              :  class(dvdb_t),intent(in) :: db
    3582              :  type(crystal_t),intent(in) :: cryst
    3583              : !arrays
    3584              :  integer,intent(in) :: ngfft(18)
    3585              :  real(dp),intent(in) :: qpt(3)
    3586              :  real(dp),intent(in) :: v1scf_rpt(2,nrpt,nfft,db%nspden)
    3587              :  real(dp),intent(out) :: v1scf_qpt(2,nfft,db%nspden)
    3588              : 
    3589              : !Local variables-------------------------------
    3590              : !scalars
    3591              :  integer,parameter :: cplex2=2
    3592              :  integer :: ir,ispden,ifft,idir,iat,timerev_q,nproc,my_rank,cnt,ierr
    3593              :  real(dp) :: wr,wi
    3594              : !arrays
    3595          488 :  integer :: symq(4,2,db%cryst%nsym)
    3596          244 :  real(dp),allocatable :: eiqr(:,:), v1r_lr(:,:)
    3597              : ! *************************************************************************
    3598              : 
    3599              :  !ABI_ERROR("Legacy code!")
    3600              : 
    3601              :  ABI_UNUSED(cryst%natom)
    3602              :  ABI_UNUSED(nspden)
    3603              : 
    3604          244 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
    3605              : 
    3606          732 :  ABI_MALLOC(v1r_lr, (2,nfft))
    3607              : 
    3608              :  ! Examine the symmetries of the q wavevector
    3609          244 :  call littlegroup_q(db%cryst%nsym, qpt, symq, db%cryst%symrec, db%cryst%symafm, timerev_q, prtvol=db%prtvol)
    3610              : 
    3611              :  ! Compute FT phases for this q-point.
    3612          732 :  ABI_MALLOC(eiqr, (2, db%my_nrpt))
    3613          244 :  call calc_eiqr(qpt, db%my_nrpt, db%my_rpt, eiqr)
    3614              : 
    3615          244 :  idir = mod(ipert-1, 3) + 1; iat = (ipert - idir) / 3 + 1
    3616              : 
    3617              :  ! Compute long-range part of the coupling potential
    3618     10437202 :  v1r_lr = zero; cnt = 0
    3619          244 :  if (db%add_lr > 0) call db%get_v1r_long_range(qpt, idir, iat, nfft, ngfft, v1r_lr)
    3620              : 
    3621              :  ! TODO: If high-symmetry q-points, one could save flops by FFT interpolating the independent
    3622              :  ! TODO: Use ZGEMM with MPI
    3623              :  ! perturbations and then rotate ...
    3624     10437446 :  v1scf_qpt = zero; cnt = 0
    3625          488 :  do ispden=1,db%nspden
    3626      3479230 :    do ifft=1,nfft
    3627      3478986 :      cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI-parallelism
    3628              : 
    3629     36342810 :      do ir=1,db%my_nrpt
    3630     32863824 :        wr = v1scf_rpt(1, ir,ifft,ispden)
    3631     32863824 :        wi = v1scf_rpt(2, ir,ifft,ispden)
    3632     32863824 :        v1scf_qpt(1,ifft,ispden) = v1scf_qpt(1,ifft,ispden) + wr*eiqr(1,ir) - wi * eiqr(2,ir)
    3633     36342810 :        v1scf_qpt(2,ifft,ispden) = v1scf_qpt(2,ifft,ispden) + wr*eiqr(2,ir) + wi * eiqr(1,ir)
    3634              :      end do
    3635              : 
    3636              :      ! Add the long-range part of the potential
    3637      3478986 :      if (db%add_lr > 0) then
    3638      2555380 :        v1scf_qpt(1,ifft,ispden) = v1scf_qpt(1,ifft,ispden) + v1r_lr(1,ifft)
    3639      2555380 :        v1scf_qpt(2,ifft,ispden) = v1scf_qpt(2,ifft,ispden) + v1r_lr(2,ifft)
    3640              :      end if
    3641      3479230 :      if (db%add_lr == 4) then
    3642            0 :        v1scf_qpt(1,ifft,ispden) = v1r_lr(1,ifft)
    3643            0 :        v1scf_qpt(2,ifft,ispden) = v1r_lr(2,ifft)
    3644              :      end if
    3645              :    end do ! ifft
    3646              : 
    3647          244 :    call xmpi_sum(v1scf_qpt(:,:,ispden), comm, ierr)
    3648              : 
    3649              :    ! Remove the phase.
    3650         1220 :    call times_eikr(-qpt, ngfft, nfft, 1, v1scf_qpt(:,:,ispden))
    3651              :  end do
    3652              : 
    3653              :  ! Be careful with gamma and cplex!
    3654          244 :  if (db%symv1 == 1) then
    3655           28 :    call v1phq_symmetrize(db%cryst, idir, iat, symq, ngfft, cplex2, nfft, db%nspden, db%nsppol, db%mpi_enreg, v1scf_qpt)
    3656              :  end if
    3657              : 
    3658          244 :  ABI_FREE(eiqr)
    3659          244 :  ABI_FREE(v1r_lr)
    3660              : 
    3661          244 : end subroutine dvdb_get_v1scf_qpt
    3662              : !!***
    3663              : 
    3664              : !----------------------------------------------------------------------
    3665              : 
    3666              : !!****f* m_dvdb/dvdb_interpolate_v1scf
    3667              : !! NAME
    3668              : !!  dvdb_interpolate_v1scf
    3669              : !!
    3670              : !! FUNCTION
    3671              : !!  Interpolate the phonon perturbation potential.
    3672              : !!  This routine is meant to replace dvdb_ftinterp_setup and dvdb_ftinterp_qpt.
    3673              : !!  It performs the interpolation one perturbation at a time.
    3674              : !!
    3675              : !! INPUTS
    3676              : !!  ngqpt(3)=Divisions of the ab-initio q-mesh.
    3677              : !!  nqshift=Number of shifts used to generated the ab-initio q-mesh.
    3678              : !!  qshift(3,nqshift)=The shifts of the ab-initio q-mesh.
    3679              : !!  nfft=Number of fft-points treated by this processors
    3680              : !!  ngfft(18)=contain all needed information about 3D FFT
    3681              : !!  nfftf=Number of fft-points on the fine grid for interpolated potential
    3682              : !!  ngfftf(18)=information on 3D FFT for interpolated potential
    3683              : !!  comm=MPI communicator
    3684              : !!
    3685              : !! OUTPUT
    3686              : !!  v1scf(2, nfft, nspden, 3*natom)= v1scf potentials on the real-space FFT mesh for the 3*natom perturbations.
    3687              : !!
    3688              : !! SOURCE
    3689              : 
    3690            0 : subroutine dvdb_interpolate_v1scf(db, cryst, qpt, ngqpt, nqshift, qshift, &
    3691              :                                   nfft, ngfft, nfftf, ngfftf, v1scf, comm)
    3692              : 
    3693              : !Arguments ------------------------------------
    3694              : !scalars
    3695              :  integer,intent(in) :: nqshift,nfft,nfftf,comm
    3696              :  class(dvdb_t),target,intent(inout) :: db
    3697              : !arrays
    3698              :  real(dp),intent(in) :: qpt(3)
    3699              :  integer,intent(in) :: ngqpt(3),ngfft(18),ngfftf(18)
    3700              :  real(dp),intent(in) :: qshift(3,nqshift)
    3701              :  real(dp),allocatable,intent(out) :: v1scf(:,:,:,:)
    3702              :  type(crystal_t),intent(in) :: cryst
    3703              : 
    3704              : !Local variables-------------------------------
    3705              : !scalars
    3706              :  integer :: ipert, nqbz, ierr, nproc, my_rank
    3707              :  !real(dp) :: work_size
    3708              : !arrays
    3709            0 :  real(dp),allocatable :: v1scf_rpt(:,:,:,:)
    3710              : ! *************************************************************************
    3711              : 
    3712            0 :  nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    3713              : 
    3714            0 :  nqbz = product(ngqpt) * nqshift
    3715            0 :  db%my_nrpt = nqbz
    3716              : 
    3717            0 :  ABI_MALLOC_OR_DIE(v1scf, (2,nfftf,db%nspden,db%natom3), ierr)
    3718            0 :  ABI_MALLOC_OR_DIE(v1scf_rpt, (2,db%my_nrpt,nfft,db%nspden), ierr)
    3719              : 
    3720            0 :  do ipert=1,db%natom3
    3721            0 :    write(std_out, "(a,i4,a,i4,a)") " Interpolating potential for perturbation ", ipert, " / ", db%natom3, ch10
    3722              : 
    3723              :    ! FIXME I think this should be ngfftf and not ngfft
    3724              :    !       Also, other calls to dvdb_ftinterp_setup should use ngfftf.
    3725              :    call dvdb_get_v1scf_rpt(db, cryst, ngqpt, nqshift, qshift, nfft, ngfft, &
    3726            0 :                            db%my_nrpt, db%nspden, ipert, v1scf_rpt, comm)
    3727              : 
    3728              :    call dvdb_get_v1scf_qpt(db, cryst, qpt, nfftf, ngfftf, db%my_nrpt, db%nspden, &
    3729            0 :                            ipert, v1scf_rpt, v1scf(:,:,:,ipert), comm)
    3730              : 
    3731            0 :    ABI_FREE(db%my_rpt)
    3732              :  end do
    3733              : 
    3734            0 :  ABI_FREE(v1scf_rpt)
    3735              : 
    3736            0 : end subroutine dvdb_interpolate_v1scf
    3737              : !!***
    3738              : 
    3739              : !----------------------------------------------------------------------
    3740              : 
    3741              : !!****f* m_dvdb/dvdb_findq
    3742              : !! NAME
    3743              : !!  dvdb_findq
    3744              : !!
    3745              : !! FUNCTION
    3746              : !!  Find the index of the q-point in db%qpts. Non zero umklapp vectors are not allowed.
    3747              : !!  Returns -1 if not found.
    3748              : !!
    3749              : !! INPUTS
    3750              : !!  qpt(3)=q-point in reduced coordinates.
    3751              : !!  [qtol]=Optional tolerance for q-point comparison.
    3752              : !!         For each reduced direction the absolute difference between the coordinates must be less that qtol
    3753              : !!
    3754              : !! SOURCE
    3755              : 
    3756         6172 : integer pure function dvdb_findq(db, qpt, qtol) result(iqpt)
    3757              : 
    3758              : !Arguments ------------------------------------
    3759              : !scalars
    3760              :  real(dp),optional,intent(in) :: qtol
    3761              :  class(dvdb_t),intent(in) :: db
    3762              : !arrays
    3763              :  real(dp),intent(in) :: qpt(3)
    3764              : 
    3765              : !Local variables-------------------------------
    3766              : !scalars
    3767              :  integer :: iq
    3768              :  real(dp) :: my_qtol
    3769              : ! *************************************************************************
    3770              : 
    3771         6172 :  my_qtol = tol6; if (present(qtol)) my_qtol = qtol
    3772         6172 :  iqpt = -1
    3773        45711 :  do iq=1,db%nqpt
    3774        55309 :    if (all(abs(db%qpts(:, iq) - qpt) < my_qtol)) then
    3775              :      iqpt = iq; exit
    3776              :    end if
    3777              :  end do
    3778              : 
    3779         6172 : end function dvdb_findq
    3780              : !!***
    3781              : 
    3782              : !----------------------------------------------------------------------
    3783              : 
    3784              : !!****f* m_dvdb/dvdb_find_qpts
    3785              : !! NAME
    3786              : !!  dvdb_find_qpts
    3787              : !!
    3788              : !! FUNCTION
    3789              : !!  Find the index of the q-point in db%qpts. Non zero umklapp vectors are not allowed.
    3790              : !!  Returns -1 if not found.
    3791              : !!
    3792              : !! INPUTS
    3793              : !!  nqpt: Number of q-points
    3794              : !!  qpt(3,nqpt): q-point in reduced coordinates.
    3795              : !!  comm: MPI communicator
    3796              : !!
    3797              : !! OUTPUT
    3798              : !!  iq2dvdb(nqpt): index of q-points in dvdb%qpts. Set to -1 if not found
    3799              : !!  ierr= Number of points **not** found
    3800              : !!
    3801              : !! SOURCE
    3802              : 
    3803           61 : integer function dvdb_find_qpts(db, nqpt, qpts, iq2dvdb, comm) result(notfound)
    3804              : 
    3805              : !Arguments ------------------------------------
    3806              : !scalars
    3807              :  class(dvdb_t),intent(in) :: db
    3808              :  integer,intent(in) :: nqpt, comm
    3809              : !arrays
    3810              :  real(dp),intent(in) :: qpts(3, nqpt)
    3811              :  integer,intent(out) :: iq2dvdb(nqpt)
    3812              : 
    3813              : !Local variables-------------------------------
    3814              : !scalars
    3815              :  integer :: iq, my_rank, nprocs, ierr
    3816              : ! *************************************************************************
    3817              : 
    3818           61 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
    3819              : 
    3820         4070 :  iq2dvdb = 0
    3821         4070 :  do iq=1,nqpt
    3822         4009 :    if (mod(iq, nprocs) /= my_rank) cycle ! MPI parallelism
    3823         4070 :    iq2dvdb(iq) = db%findq(qpts(:, iq))
    3824              :  end do
    3825              : 
    3826           61 :  call xmpi_sum(iq2dvdb, comm, ierr)
    3827         4070 :  notfound = count(iq2dvdb == -1)
    3828              : 
    3829           61 : end function dvdb_find_qpts
    3830              : !!***
    3831              : 
    3832              : !----------------------------------------------------------------------
    3833              : 
    3834              : !!****f* m_dvdb/dvdb_need_ftinterp
    3835              : !! NAME
    3836              : !!  dvdb_need_ftinterp
    3837              : !!
    3838              : !! FUNCTION
    3839              : !!  Check whether input list of q-points requires Fourier interpolation.
    3840              : !!
    3841              : !! INPUTS
    3842              : !!  nqpt: Number of q-points
    3843              : !!  qpt(3,nqpt): q-point in reduced coordinates.
    3844              : !!
    3845              : !! OUTPUT
    3846              : !!  qmap_symrec(6, nqpt)
    3847              : !!  need_ftinterp
    3848              : !!
    3849              : !! SOURCE
    3850              : 
    3851            7 : subroutine dvdb_need_ftinterp(db, nqpt, qpts, qptopt,  qmap_symrec, need_ftinterp)
    3852              : 
    3853              : !Arguments ------------------------------------
    3854              : !scalars
    3855              :  class(dvdb_t),intent(in) :: db
    3856              :  integer,intent(in) :: nqpt, qptopt
    3857              :  logical,intent(out) :: need_ftinterp
    3858              : !arrays
    3859              :  real(dp),intent(in) :: qpts(3, nqpt)
    3860              :  integer,allocatable,intent(out) :: qmap_symrec(:,:)
    3861              : 
    3862              : !Local variables-------------------------------
    3863              : !scalars
    3864              :  integer :: iq, iq_ibz, db_iqpt, qtimrev
    3865            7 :  type(krank_t) :: qrank
    3866              : !arrays
    3867              :  real(dp) :: qq_ibz(3)
    3868              : ! *************************************************************************
    3869              : 
    3870            7 :  need_ftinterp = .False.
    3871            7 :  call qrank%init(db%nqpt, db%qpts, compute_invrank=.False.)
    3872              : 
    3873            7 :  qtimrev = kpts_timrev_from_kptopt(qptopt)
    3874           21 :  ABI_MALLOC(qmap_symrec, (6, nqpt))
    3875              : 
    3876            7 :  if (kpts_map("symrec", qtimrev, db%cryst, qrank, nqpt, qpts, qmap_symrec) /= 0) then
    3877              :    ! There's at least on-qpoint in qpts that is not the IBZ image of db%qpts.
    3878            5 :    need_ftinterp = .True.; call qrank%free()
    3879            5 :    return
    3880              :  end if
    3881              : 
    3882              :  ! All the IBZ images must be in the DVDB
    3883           14 :  do iq=1,nqpt
    3884           12 :    iq_ibz = qmap_symrec(1, iq)
    3885           48 :    qq_ibz = db%qpts(:, iq_ibz)
    3886           12 :    db_iqpt = db%findq(qq_ibz)
    3887           14 :    if (db_iqpt == -1) then
    3888            0 :      need_ftinterp = .True.; exit
    3889              :    end if
    3890              :  end do
    3891              : 
    3892            2 :  call qrank%free()
    3893              : 
    3894            7 : end subroutine dvdb_need_ftinterp
    3895              : !!***
    3896              : 
    3897              : !!****f* m_dvdb/dvdb_set_pert_distrib
    3898              : !! NAME
    3899              : !!  dvdb_set_pert_distrib
    3900              : !!
    3901              : !! FUNCTION
    3902              : !!  Activate MPI distribution of the 3*natom perturbations.
    3903              : !!
    3904              : !! INPUTS
    3905              : !!  my_npert=Number of perturbations treated by this rank
    3906              : !!  natom3= 3 * natom
    3907              : !!  my_pinfo(3, my_npert)
    3908              : !!     my_pinfo(1, ip) gives the `idir` index of the ip-th perturbation.
    3909              : !!     my_pinfo(2, ip) gives the `ipert` index of the ip-th perturbation.
    3910              : !!     my_pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3
    3911              : !!  pert_table(2, natom3)
    3912              : !!      pert_table(1, npert): rank of the processor treating this atomic perturbation.
    3913              : !!      pert_table(2, npert): imyp index in my_pinfo table, -1 if this rank is not treating ipert.
    3914              : !!  comm_pert=MPI communicator used to distribute the 3*natom perturbations
    3915              : !!
    3916              : !! SOURCE
    3917              : 
    3918            0 : subroutine dvdb_set_pert_distrib(self, my_npert, natom3, my_pinfo, pert_table, comm_pert)
    3919              : 
    3920              : !Arguments ------------------------------------
    3921              : !scalars
    3922              :  class(dvdb_t),intent(inout) :: self
    3923              :  integer,intent(in) :: my_npert, natom3, comm_pert
    3924              : !arrays
    3925              :  integer,intent(in) :: my_pinfo(3,my_npert), pert_table(2,natom3)
    3926              : ! *************************************************************************
    3927              : 
    3928            0 :  self%comm_pert = comm_pert
    3929            0 :  self%nprocs_pert = xmpi_comm_size(comm_pert)
    3930            0 :  self%me_pert = xmpi_comm_rank(comm_pert)
    3931            0 :  self%my_npert = my_npert
    3932              : 
    3933            0 :  ABI_SFREE(self%my_pinfo)
    3934            0 :  ABI_SFREE(self%pert_table)
    3935            0 :  call alloc_copy(my_pinfo, self%my_pinfo)
    3936            0 :  call alloc_copy(pert_table, self%pert_table)
    3937              : 
    3938            0 :  if (self%debug) then
    3939            0 :    write(std_out, *)"Activating perturbation over perturbations:"
    3940            0 :    write(std_out, *)"nprocs_pert: ", self%nprocs_pert
    3941            0 :    write(std_out, *)"my_pinfo: ",self%my_pinfo
    3942            0 :    write(std_out, *)"pert_table: ",self%pert_table
    3943              :  end if
    3944              : 
    3945            0 : end subroutine dvdb_set_pert_distrib
    3946              : !!***
    3947              : 
    3948              : !!****f* m_dvdb/dvdb_seek
    3949              : !! NAME
    3950              : !!  dvdb_seek
    3951              : !!
    3952              : !! FUNCTION
    3953              : !!  Move the internal file pointer so that it points to the
    3954              : !!  block with (idir, ipert, iqpt). Needed only if dvdb%iomode==IO_MODE_FORTRAN
    3955              : !!
    3956              : !! INPUTS
    3957              : !!   idir,ipert,iqpt = (direction, perturbation, q-point) indices
    3958              : !!
    3959              : !! SIDE EFFECTS
    3960              : !!   db<type(dvdb_t)>: modifies db%current_fpos.
    3961              : !!
    3962              : !! SOURCE
    3963              : 
    3964         5360 : subroutine dvdb_seek(db, idir, ipert, iqpt)
    3965              : 
    3966              : !Arguments ------------------------------------
    3967              :  integer,intent(in)  :: idir, ipert, iqpt
    3968              :  type(dvdb_t),intent(inout) :: db
    3969              : 
    3970              : !Local variables-------------------------------
    3971              :  integer :: pos_now,pos_wanted,ii,ispden,nn,ierr
    3972              :  real(dp),parameter :: fake_qpt(3)=zero
    3973              :  character(len=500) :: msg
    3974              : ! *************************************************************************
    3975              : 
    3976         5360 :  if (db%iomode == IO_MODE_FORTRAN) then
    3977         5360 :    pos_now = db%current_fpos
    3978         5360 :    pos_wanted = db%pos_dpq(idir,ipert,iqpt)
    3979         5360 :    ABI_CHECK(pos_wanted /= 0, "pos_wanted cannot be zero!")
    3980              : 
    3981              :    ! Optimal access.
    3982         6416 :    if (pos_now == pos_wanted) return
    3983              : 
    3984         1056 :    if (pos_wanted < pos_now) then
    3985              :      ! Backspace previous records and header
    3986              :      ! but only if nn <= pos_wanted else rewind file and skip pos_wanted potentials (should be faster)
    3987          850 :      nn = pos_now - pos_wanted
    3988          850 :      if (nn <= pos_wanted) then
    3989         3594 :        do ii=1,nn
    3990              :          !write(std_out, *)"backspacing"
    3991         2974 :          if (db%version > 1) backspace(unit=db%fh, err=10, iomsg=msg)
    3992         5948 :          do ispden=1,db%nspden
    3993         5948 :            backspace(unit=db%fh, err=10, iomsg=msg)
    3994              :          end do
    3995         2974 :          ierr = db%hdr_ref%backspace(db%fh, msg)
    3996         3594 :          if (ierr /= 0) goto 10
    3997              :        end do
    3998          620 :        db%current_fpos = pos_wanted; return
    3999              :      else
    4000              :        ! rewind the file and read it from the beginning
    4001          230 :        if (dvdb_rewind(db, msg) /= 0) then
    4002            0 :          ABI_ERROR(msg)
    4003              :        end if
    4004              :        nn = pos_wanted
    4005              :      end if
    4006              : 
    4007              :    else
    4008          206 :      nn = pos_wanted - pos_now + 1
    4009              :    end if
    4010              : 
    4011         4943 :    do ii=1,nn-1
    4012              :      !write(std_out,*)"in seek with ii: ",ii,"pos_wanted: ",pos_wanted
    4013         4507 :      if (my_hdr_skip(db%fh, -1, -1, fake_qpt, msg) /= 0) then
    4014            0 :        ABI_ERROR(msg)
    4015              :      end if
    4016              :      ! Skip the records with v1.
    4017         9014 :      do ispden=1,db%nspden
    4018         9014 :        read(db%fh, err=10, iomsg=msg)
    4019              :      end do
    4020              :      ! Skip record with rhog1_g0 (if present)
    4021         4943 :      if (db%version > 1) read(db%fh, err=10, iomsg=msg)
    4022              :    end do
    4023              : 
    4024          436 :    db%current_fpos = pos_wanted
    4025              : 
    4026              :  else
    4027            0 :    ABI_ERROR("Should not be called when iomode /= IO_MODE_FORTRAN")
    4028              :  end if
    4029              : 
    4030            0 :  return
    4031              : 
    4032              :  ! Handle Fortran IO error
    4033              : 10 continue
    4034            0 :  msg = sjoin("Error while reading", db%path, ch10, msg)
    4035              : 
    4036              : end subroutine dvdb_seek
    4037              : !!***
    4038              : 
    4039              : !----------------------------------------------------------------------
    4040              : 
    4041              : !!****f* m_dvdb/dvdb_rewind
    4042              : !! NAME
    4043              : !!  dvdb_rewind
    4044              : !!
    4045              : !! FUNCTION
    4046              : !!   Rewind the file and move to the first header. Needed only if dvdb%iomode==IO_MODE_FORTRAN
    4047              : !!   Return exit code and error message in msg if ierr != 0.
    4048              : !!
    4049              : !! SOURCE
    4050              : 
    4051          230 : integer function dvdb_rewind(db, msg) result(ierr)
    4052              : 
    4053              : !Arguments ------------------------------------
    4054              :  type(dvdb_t),intent(inout) :: db
    4055              :  character(len=*),intent(out) :: msg
    4056              : ! *************************************************************************
    4057              : 
    4058          230 :  ierr = 0
    4059          230 :  if (db%iomode == IO_MODE_FORTRAN) then
    4060          230 :    rewind(db%fh, err=10, iomsg=msg)
    4061          230 :    read(db%fh, err=10, iomsg=msg)  ! version
    4062          230 :    read(db%fh, err=10, iomsg=msg)  ! numv1
    4063          230 :    db%current_fpos = 1
    4064              : 
    4065              :  else
    4066            0 :    ierr = -1
    4067            0 :    msg = "should not be called when iomode /= IO_MODE_FORTRAN"
    4068              :  end if
    4069              : 
    4070              :  return
    4071              : 
    4072              :  ! Handle Fortran IO error
    4073              : 10 continue
    4074            0 :  ierr = 1
    4075            0 :  msg = sjoin("Error while reading", db%path, ch10, msg)
    4076              : 
    4077          230 : end function dvdb_rewind
    4078              : !!***
    4079              : 
    4080              : !----------------------------------------------------------------------
    4081              : 
    4082              : !!****f* m_dvdb/my_hdr_skip
    4083              : !! NAME
    4084              : !!  my_hdr_skip
    4085              : !!
    4086              : !! FUNCTION
    4087              : !!  Skip the header without rewinding the file. Return exit code.
    4088              : !!
    4089              : !! NOTES
    4090              : !!  Because hdr_skip rewinds the file and I'm not gonna change that ugly code.
    4091              : !!
    4092              : !! SOURCE
    4093              : 
    4094         9867 : integer function my_hdr_skip(unit, idir, ipert, qpt, msg) result(ierr)
    4095              : 
    4096              : !Arguments ------------------------------------
    4097              : !scalars
    4098              :  integer,intent(in) :: unit,idir,ipert
    4099              :  real(dp),intent(in) :: qpt(3)
    4100              :  character(len=500),intent(out) :: msg
    4101              : 
    4102              : !Local variables-------------------------------
    4103              :  integer :: fform
    4104         9867 :  type(hdr_type) :: tmp_hdr
    4105              : !************************************************************************
    4106              : 
    4107         9867 :  ierr = 0; msg = ""
    4108         9867 :  call tmp_hdr%fort_read(unit, fform)
    4109         9867 :  ierr = dvdb_check_fform(fform, "read_dvdb", msg)
    4110         9867 :  if (ierr /= 0) return
    4111              : 
    4112         9867 :  if (idir /= -1 .and. ipert /= -1) then
    4113              :    if (idir /= mod(tmp_hdr%pertcase-1, 3) + 1 .or. &
    4114        21440 :        ipert /= (tmp_hdr%pertcase - idir) / 3 + 1 .or. &
    4115              :        any(abs(qpt - tmp_hdr%qptn) > tol14)) then
    4116            0 :          msg = "Perturbation index on file does not match the one expected by the caller"
    4117            0 :          ierr = -1
    4118              :    end if
    4119              :  end if
    4120              : 
    4121         9867 :  call tmp_hdr%free()
    4122              : 
    4123         9867 : end function my_hdr_skip
    4124              : !!***
    4125              : 
    4126              : !----------------------------------------------------------------------
    4127              : 
    4128              : !!****f* m_dvdb/dvdb_list_perts
    4129              : !! NAME
    4130              : !!  dvdb_list_perts
    4131              : !!
    4132              : !! FUNCTION
    4133              : !!  Given a q-point mesh, this routine checks if all the (phonon) perturbations
    4134              : !!  are available taking into account symmetries.
    4135              : !!
    4136              : !! INPUTS
    4137              : !!  ngqpt(3)=Q-mesh divisions. If all(ngqpt == -1), the list of q-points in the DVDB
    4138              : !!    (i.e. db%qpts) is analyzed instead of the q-points generated from ngqpt.
    4139              : !!  [unit]=Unit number for output. Default `std_out`.
    4140              : !!
    4141              : !! OUTPUT
    4142              : !!  npert_miss = Number of missing perturbations.
    4143              : !!
    4144              : !! SOURCE
    4145              : 
    4146          116 : subroutine dvdb_list_perts(db, ngqpt, npert_miss, unit)
    4147              : 
    4148              : !Arguments ------------------------------------
    4149              :  class(dvdb_t),target,intent(in) :: db
    4150              :  integer,intent(out) :: npert_miss
    4151              :  integer,optional,intent(in) :: unit
    4152              : !arrays
    4153              :  integer,intent(in) :: ngqpt(3)
    4154              : 
    4155              : !Local variables-------------------------------
    4156              : !scalars
    4157              :  integer :: npert_redund,miss_q,idir,ipert,iv1,psy,weird_q,enough
    4158              :  integer :: iq_ibz,nqibz,iq_file,qptopt,nshiftq,ii,timerev_q,unt,nqbz
    4159              :  character(len=500) :: msg,ptype,found
    4160              :  type(crystal_t),pointer :: cryst
    4161              : !arrays
    4162              :  integer :: rfdir(3),qptrlatt(3,3)
    4163          116 :  integer,allocatable :: pertsy(:,:),symq(:,:,:),rfpert(:)
    4164              :  real(dp) :: qq(3),shiftq(3,1)
    4165          116 :  real(dp),allocatable :: qibz(:,:),wtq(:),qbz(:,:)
    4166              : ! *************************************************************************
    4167              : 
    4168          116 :  unt = std_out; if (present(unit)) unt = unit
    4169          116 :  cryst => db%cryst
    4170              : 
    4171          464 :  if (all(ngqpt == -1)) then
    4172              :    ! Will test the q-points in db
    4173          116 :    call alloc_copy(db%qpts, qibz)
    4174          116 :    nqibz = db%nqpt
    4175              :  else
    4176              :    ! Will test the q-points in the IBZ associated to ngqpt hence build IBZ and BZ from ngqpt.
    4177            0 :    qptopt = 1; shiftq = zero; nshiftq = 1; qptrlatt = 0
    4178            0 :    do ii=1,3
    4179            0 :      qptrlatt(ii, ii) = ngqpt(ii)
    4180              :    end do
    4181              : 
    4182            0 :    call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, nshiftq, shiftq, nqibz, qibz, wtq, nqbz, qbz)
    4183              : 
    4184            0 :    ABI_FREE(qbz)
    4185            0 :    ABI_FREE(wtq)
    4186              :  end if
    4187              : 
    4188              :  ! Initialize the list of perturbations rfpert and rdfir
    4189              :  ! WARNING: Only phonon perturbations are considered for the time being.
    4190          348 :  ABI_MALLOC(rfpert,(db%mpert))
    4191         1602 :  rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1
    4192              : 
    4193          348 :  ABI_MALLOC(symq, (4,2,cryst%nsym))
    4194          348 :  ABI_MALLOC(pertsy, (3,db%mpert))
    4195              : 
    4196              :  ! Loop over the q-points in the IBZ and test whether the q-point is present
    4197              :  ! and if all the independent perturbations are available.
    4198              :  !   `npert_miss` is the number of irreducible perturbations not found in the DVDB (critical)
    4199              :  !   `npert_redund` is the number of redundant perturbations found in the DVDB (not critical)
    4200              :  !
    4201          116 :  enough = 5; if (db%prtvol > 0) enough = nqibz + 1
    4202          116 :  npert_miss = 0; npert_redund = 0
    4203          798 :  do iq_ibz=1,nqibz
    4204          682 :    if (iq_ibz == enough)  then
    4205           45 :      call wrtout(unt,' More than 20 q-points with prtvol == 0. Only important messages will be printed...')
    4206              :    end if
    4207         2728 :    qq = qibz(:,iq_ibz)
    4208          682 :    iq_file = db%findq(qq)
    4209              : 
    4210              :    ! Examine the symmetries of the q wavevector
    4211          682 :    call littlegroup_q(cryst%nsym,qq,symq,cryst%symrec,cryst%symafm,timerev_q,prtvol=db%prtvol)
    4212              : 
    4213              :    ! Determine the symmetrical perturbations. Meaning of pertsy:
    4214              :    !    0 for non-target perturbations
    4215              :    !    1 for basis perturbations
    4216              :    !   -1 for perturbations that can be found from basis perturbations
    4217              :    call irreducible_set_pert(cryst%indsym,db%mpert,cryst%natom,cryst%nsym,&
    4218          682 :      pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel)
    4219              : 
    4220          682 :    if (iq_file /= -1) then
    4221              :      ! This q-point is in the DVDB. Test if all the independent perturbations are available.
    4222          682 :      if (iq_ibz <= enough)  then
    4223          526 :        call wrtout(unt, sjoin(" qpoint:", ktoa(qq), "is present in the DVDB file"))
    4224          526 :        call wrtout(unt,' The list of irreducible perturbations for this q vector is:')
    4225              :      end if
    4226          682 :      ii = 0; weird_q = 0; miss_q = 0
    4227         6039 :      do ipert=1,db%mpert
    4228        22110 :        do idir=1,3
    4229        16071 :          psy = pertsy(idir,ipert)
    4230        16071 :          if (psy == 0) cycle
    4231         3795 :          iv1 = db%pos_dpq(idir,ipert,iq_file)
    4232         3795 :          ptype = "independent"; if (psy == -1) ptype = "symmetric"
    4233         3795 :          found = "Yes"; if (iv1 == 0) found = "No"
    4234              : 
    4235         3795 :          if (psy == 1 .and. iv1 == 0) miss_q = miss_q + 1
    4236         3795 :          if (psy == -1 .and. iv1 /= 0) weird_q = weird_q + 1
    4237              : 
    4238         3795 :          ii=ii+1
    4239         9152 :          if (iq_ibz <= enough)  then
    4240         2886 :            write(msg,'(i5,a,i2,a,i4,4a)')ii,')  idir=',idir,', ipert=',ipert,", type=",trim(ptype),", found=",trim(found)
    4241         2886 :            call wrtout(unt, msg)
    4242              :          end if
    4243              :        end do
    4244              :      end do
    4245              : 
    4246          682 :      if (weird_q /= 0) then
    4247            0 :        write(msg,"(a,i0,a)")" DVDB is overcomplete. ",weird_q, " perturbation(s) can be reconstructed by symmetry."
    4248            0 :        call wrtout(unt, msg)
    4249              :      end if
    4250              : 
    4251          682 :      npert_redund = npert_redund + weird_q
    4252          682 :      npert_miss = npert_miss + miss_q
    4253          682 :      if (miss_q /=0) then
    4254            0 :        call wrtout(unt, sjoin(" WARNING:", itoa(miss_q), "independent perturbation(s) are missing!."))
    4255              :      end if
    4256              : 
    4257              :    else
    4258              :      ! This q-point is not present in dvdb. Print the list of independent perturbations.
    4259            0 :      call wrtout(unt, sjoin(" qpoint:", ktoa(qq), "is NOT present in the DVDB file"))
    4260            0 :      call wrtout(unt,' The list of irreducible perturbations for this q vector is:')
    4261            0 :      ii = 0
    4262            0 :      do ipert=1,db%mpert
    4263            0 :        do idir=1,3
    4264            0 :          if (pertsy(idir,ipert) == 1) then
    4265            0 :            ii=ii+1
    4266            0 :            write(msg,'(i5,a,i2,a,i4,a)')ii,')  idir=',idir,', ipert=',ipert,", type=independent, found=No"
    4267            0 :            call wrtout(unt, msg)
    4268            0 :            npert_miss = npert_miss + 1
    4269              :          end if
    4270              :        end do
    4271              :      end do
    4272              :    end if
    4273              : 
    4274         1480 :    if (iq_ibz <= enough) call wrtout(unt," ")
    4275              :  end do ! iq_ibz
    4276              : 
    4277          116 :  if (npert_miss /= 0) then
    4278            0 :    call wrtout(unt, sjoin(ch10, " There are ",itoa(npert_miss), "independent perturbations missing!"))
    4279              :  else
    4280          116 :    call wrtout(unt, " All the independent perturbations are available")
    4281          116 :    if (npert_redund /= 0) then
    4282            0 :      call wrtout(unt, " Note however that the DVDB is overcomplete as symmetric perturbations are present.")
    4283              :    end if
    4284              :  end if
    4285              : 
    4286          116 :  ABI_FREE(qibz)
    4287          116 :  ABI_FREE(rfpert)
    4288          116 :  ABI_FREE(symq)
    4289          116 :  ABI_FREE(pertsy)
    4290              : 
    4291          116 : end subroutine dvdb_list_perts
    4292              : !!***
    4293              : 
    4294              : !----------------------------------------------------------------------
    4295              : 
    4296              : !!****f* m_dvdb/dvdb_merge_files
    4297              : !! NAME
    4298              : !!  dvdb_merge_files
    4299              : !!
    4300              : !! FUNCTION
    4301              : !!  Merge a list of POT1 or DEN1 files.
    4302              : !!
    4303              : !! INPUT
    4304              : !!  nfiles=Number of files to be merged.
    4305              : !!  dvdb_filepath=Name of output DVDB file.
    4306              : !!  prtvol=Verbosity level.
    4307              : !!
    4308              : !! SIDE EFFECTS
    4309              : !!   v1files=List of file names to merge. This list could be changed if POT1 files in netcdf format are found.
    4310              : !!
    4311              : !! SOURCE
    4312              : 
    4313           17 : subroutine dvdb_merge_files(nfiles, v1files, dvdb_filepath, prtvol)
    4314              : 
    4315              : !Arguments ------------------------------------
    4316              : !scalars
    4317              :  integer,intent(in) :: nfiles,prtvol
    4318              :  character(len=*),intent(in) :: dvdb_filepath
    4319              :  character(len=*),intent(inout) :: v1files(nfiles)
    4320              : 
    4321              : !Local variables-------------------------------
    4322              : !scalars
    4323              : ! Here I made a mistake because 102 corresponds to GS potentials
    4324              : ! as a consequence DVDB files generated with version <= 8.1.6
    4325              : ! contain list of potentials with fform = 102.
    4326              :  !integer :: fform_pot=102
    4327              :  integer :: fform_pot = 111, gpu_option0 = 0
    4328              :  integer :: ii,jj,fform,ount,cplex,nfft,ifft,ispden,nperts
    4329              :  integer :: n1,n2,n3,v1_varid,ierr, npert_miss, first_fform
    4330              :  logical :: qeq0
    4331              :  character(len=500) :: msg
    4332              :  type(hdr_type),pointer :: hdr1
    4333         1394 :  type(dvdb_t) :: dvdb
    4334              : !arrays
    4335           34 :  integer :: units(nfiles)
    4336              :  real(dp) :: rhog1_g0(2)
    4337           17 :  real(dp),allocatable :: v1(:)
    4338           34 :  logical :: has_rhog1_g0(nfiles)
    4339           17 :  type(hdr_type),target,allocatable :: hdr1_list(:)
    4340              : !************************************************************************
    4341              : 
    4342           17 :  if (file_exists(dvdb_filepath)) then
    4343            0 :    ABI_ERROR(sjoin("Cannot overwrite existing file:", dvdb_filepath))
    4344              :  end if
    4345              : 
    4346              :  ! If a file is not found, try the netcdf version and change v1files accordingly.
    4347          296 :  do ii=1,nfiles
    4348          296 :    if (nctk_try_fort_or_ncfile(v1files(ii), msg) /= 0) then
    4349            0 :      ABI_ERROR(msg)
    4350              :    end if
    4351              :  end do
    4352              : 
    4353              :  ! Read the headers
    4354          330 :  ABI_MALLOC(hdr1_list, (nfiles))
    4355           17 :  nperts = size(hdr1_list)
    4356              : 
    4357              :  ! Write dvdb file (we only support fortran binary format)
    4358           17 :  if (open_file(dvdb_filepath, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then
    4359            0 :    ABI_ERROR(msg)
    4360              :  end if
    4361           17 :  write(ount, err=10, iomsg=msg) dvdb_last_version
    4362           17 :  write(ount, err=10, iomsg=msg) nperts
    4363              : 
    4364              :  ! Validate headers.
    4365              :  ! TODO: Should perform consistency check on the headers
    4366              :  ! rearrange them in blocks of q-points for efficiency reason.
    4367              :  ! ignore POT1 files that do not correspond to atomic perturbations.
    4368              :  ! Add POT file from GS run to support Sternheimer in eph_task = 4
    4369              : 
    4370          296 :  do ii=1,nfiles
    4371          279 :    write(std_out,"(a,i0,2a)")"- Reading header of file [",ii,"]: ",trim(v1files(ii))
    4372              : 
    4373          279 :    if (endswith(v1files(ii), ".nc")) then
    4374          279 :       NCF_CHECK(nctk_open_read(units(ii), v1files(ii), xmpi_comm_self))
    4375          279 :       call hdr1_list(ii)%ncread(units(ii), fform)
    4376              :    else
    4377            0 :      if (open_file(v1files(ii), msg, newunit=units(ii), form="unformatted", action="read", status="old") /= 0) then
    4378            0 :        ABI_ERROR(msg)
    4379              :      end if
    4380            0 :      call hdr1_list(ii)%fort_read(units(ii), fform)
    4381              :    end if
    4382              : 
    4383          279 :    if (dvdb_check_fform(fform, "merge_dvdb", msg) /= 0) then
    4384            0 :      ABI_ERROR(sjoin("While reading:", v1files(ii), msg))
    4385              :    end if
    4386          279 :    if (prtvol > 0) call hdr1_list(ii)%echo(fform, 3, unit=std_out)
    4387          279 :    if (hdr1_list(ii)%pertcase == 0) then
    4388            0 :      ABI_ERROR(sjoin("Found GS potential:", v1files(ii)))
    4389              :    end if
    4390              :    !write(std_out,*)"done", trim(v1files(ii))
    4391              : 
    4392          279 :    if (ii == 1) then
    4393           17 :      first_fform = fform
    4394              :    else
    4395          262 :      ABI_CHECK_IEQ(fform, first_fform, "Trying to merge files with different quantities")
    4396              :    end if
    4397              : 
    4398              :    ! Supported fform:
    4399              :    ! 109  POT1 files without vh1(G=0)
    4400              :    ! 111  POT1 files with extra record with vh1(G=0) after FFT data.
    4401              :    ! 54   RHO1 files (treating DRHODB as DVDB)
    4402              : 
    4403          279 :    has_rhog1_g0(ii) = .True.
    4404          279 :    if (any(fform == [54, 109])) has_rhog1_g0(ii) = .False.
    4405              : 
    4406          279 :    write(std_out,"(a,i0,2a)")"- Merging file [",ii,"]: ",trim(v1files(ii))
    4407          279 :    jj = ii
    4408          279 :    hdr1 => hdr1_list(jj)
    4409          279 :    if (any(fform == pot1_fforms)) then
    4410          199 :      call hdr1%fort_write(ount, fform_pot, ierr)
    4411              :    else
    4412           80 :      call hdr1%fort_write(ount, den1_fforms(1), ierr)
    4413              :    end if
    4414          279 :    ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0")
    4415              : 
    4416          279 :    qeq0 = (hdr1%qptn(1)**2+hdr1%qptn(2)**2+hdr1%qptn(3)**2<1.d-14)
    4417          279 :    cplex = 2; if (qeq0) cplex = 1
    4418         1116 :    nfft = product(hdr1%ngfft(1:3))
    4419          279 :    n1 = hdr1%ngfft(1); n2 = hdr1%ngfft(2); n3 = hdr1%ngfft(3)
    4420              : 
    4421          837 :    ABI_MALLOC(v1, (cplex*nfft))
    4422              : 
    4423          279 :    if (.not. endswith(v1files(ii), ".nc")) then
    4424              :       ! Fortran IO
    4425            0 :       do ispden=1,hdr1%nspden
    4426            0 :         read(units(jj), err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft)
    4427            0 :         write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft)
    4428              :       end do
    4429              :       ! Add rhog1(G=0)
    4430            0 :       rhog1_g0 = zero
    4431            0 :       if (has_rhog1_g0(jj)) read(units(jj), err=10, iomsg=msg) rhog1_g0
    4432            0 :       if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    4433              :    else
    4434              :       ! Netcdf IO
    4435              :       ! netcdf array has shape [cplex, n1, n2, n3, nspden]
    4436          279 :       if (any(fform == pot1_fforms)) then
    4437          199 :         NCF_CHECK(nf90_inq_varid(units(ii), "first_order_potential", v1_varid))
    4438          398 :         do ispden=1,hdr1%nspden
    4439         2189 :           NCF_CHECK(nf90_get_var(units(ii), v1_varid, v1, start=[1,1,1,1,ispden], count=[cplex, n1, n2, n3, 1]))
    4440          398 :           write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft)
    4441              :         end do
    4442              :         ! Add rhog1(G=0)
    4443          199 :         rhog1_g0 = zero
    4444          199 :         if (has_rhog1_g0(jj)) then
    4445          199 :           NCF_CHECK(nf90_get_var(units(ii), nctk_idname(units(ii), "rhog1_g0"), rhog1_g0))
    4446              :         end if
    4447           80 :       else if (any(fform == den1_fforms)) then
    4448              :         ! v below should read as rho
    4449           80 :         NCF_CHECK(nf90_inq_varid(units(ii), "first_order_density", v1_varid))
    4450          160 :         do ispden=1,hdr1%nspden
    4451          880 :           NCF_CHECK(nf90_get_var(units(ii), v1_varid, v1, start=[1,1,1,1,ispden], count=[cplex, n1, n2, n3, 1]))
    4452          160 :           write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft)
    4453              :         end do
    4454              :       else
    4455            0 :         ABI_ERROR(sjoin("Don't know how to handle fform:", itoa(fform)))
    4456              :       end if
    4457          279 :       if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    4458              :    end if
    4459              : 
    4460          279 :    if (.not. endswith(v1files(ii), ".nc")) then
    4461            0 :      close(units(ii))
    4462              :    else
    4463          279 :      NCF_CHECK(nf90_close(units(ii)))
    4464              :    end if
    4465              : 
    4466          296 :    ABI_FREE(v1)
    4467              :  end do ! nperts
    4468              : 
    4469           17 :  close(ount)
    4470              : 
    4471          296 :  do ii=1,size(hdr1_list)
    4472          296 :    call hdr1_list(ii)%free()
    4473              :  end do
    4474          296 :  ABI_FREE(hdr1_list)
    4475              : 
    4476           17 :  write(std_out,"(a,i0,a)")" Merged successfully ", nfiles, " files"
    4477              : 
    4478              :  ! List available perturbations.
    4479           17 :  call dvdb%init(dvdb_filepath, gpu_option0, xmpi_comm_self)
    4480           34 :  call dvdb%print([std_out], "", 0)
    4481           17 :  call dvdb%list_perts([-1, -1, -1], npert_miss)
    4482           17 :  call dvdb%free()
    4483              : 
    4484           17 :  return
    4485              : 
    4486              :  ! Handle Fortran IO error
    4487              : 10 continue
    4488            0 :  ABI_ERROR(sjoin("Error while merging files", ch10, msg))
    4489              : 
    4490           17 : end subroutine dvdb_merge_files
    4491              : !!***
    4492              : 
    4493              : !!****f* m_dvdb/calc_eiqr
    4494              : !! NAME
    4495              : !!  calc_eiqr
    4496              : !!
    4497              : !! FUNCTION
    4498              : !!   Compute e^{iq.r} for nrpt R-points.
    4499              : !!
    4500              : !! INPUTS
    4501              : !!
    4502              : !! OUTPUT
    4503              : !!
    4504              : !! SOURCE
    4505              : 
    4506         5596 : subroutine calc_eiqr(qpt, nrpt, rpt, eiqr)
    4507              : 
    4508              : !Arguments -------------------------------
    4509              : !scalars
    4510              :  integer,intent(in) :: nrpt
    4511              : !arrays
    4512              :  real(dp),intent(in) :: qpt(3), rpt(3, nrpt)
    4513              :  real(dp),intent(out) :: eiqr(2, nrpt)
    4514              : 
    4515              : !Local variables -------------------------
    4516              : !scalars
    4517              :  integer :: ir
    4518              :  real(dp) :: qr
    4519              : ! *********************************************************************
    4520              : 
    4521              : !$OMP PARALLEL DO PRIVATE(qr)
    4522       222124 :  do ir=1,nrpt
    4523       866112 :    qr = two_pi * dot_product(qpt, rpt(:,ir))
    4524       222124 :    eiqr(1, ir) = cos(qr); eiqr(2, ir) = sin(qr)
    4525              :  end do
    4526              : 
    4527         5596 : end subroutine calc_eiqr
    4528              : !!***
    4529              : 
    4530              : !----------------------------------------------------------------------
    4531              : 
    4532              : !!****f* m_dvdb/dvdb_check_fform
    4533              : !! NAME
    4534              : !!  dvdb_check_fform
    4535              : !!
    4536              : !! FUNCTION
    4537              : !!  Check the value of fform. Return exit status and error message.
    4538              : !!
    4539              : !! INPUTS
    4540              : !!   fform=Value read from the header
    4541              : !!   mode="merge_dvdb" to check the value of fform when we are merging POT1 files
    4542              : !!        "read_dvdb" when we are reading POT1 files from a DVDB file.
    4543              : !!
    4544              : !! OUTPUT
    4545              : !!   errmsg=String with error message if ierr /= 0
    4546              : !!
    4547              : !! SOURCE
    4548              : 
    4549        12349 : integer function dvdb_check_fform(fform, mode, errmsg) result(ierr)
    4550              : 
    4551              : !Arguments ------------------------------------
    4552              :  integer,intent(in) :: fform
    4553              :  character(len=*),intent(in) :: mode
    4554              :  character(len=*),intent(out) :: errmsg
    4555              : ! *************************************************************************
    4556              : 
    4557        12349 :  ierr = 0
    4558              : 
    4559              :  ! Here I made a mistake because 102 corresponds to GS potentials
    4560              :  ! as a consequence DVDB files generated with version <= 8.1.6
    4561              :  ! contain list of potentials with fform = 102.
    4562              :  !
    4563              :  ! In GWPT, one may want to use DRHODB as DVDB. For this, here I
    4564              :  ! also allow merging and reading first order density with fform = 54.
    4565              :  !
    4566              :  !integer :: fform_rho=54
    4567              :  !integer :: fform_pot=102
    4568              :  !integer :: fform_pot=109
    4569              :  !integer :: fform_pot=111
    4570              : 
    4571        12349 :  if (fform == 0) then
    4572            0 :    errmsg = "fform == 0! Either corrupted/nonexistent file or IO error"
    4573            0 :    ierr = 42; return
    4574              :  end if
    4575              : 
    4576          279 :  select case (mode)
    4577              :  case ("merge_dvdb")
    4578          279 :     if (all(fform /= [54, 109, 111])) then
    4579            0 :       errmsg = sjoin("fform:", itoa(fform), "is not supported in `merge_dvdb` mode")
    4580            0 :       ierr = 1; return
    4581              :     end if
    4582              : 
    4583              :  case ("read_dvdb")
    4584        12070 :     if (all(fform /= [54, 102, 109, 111])) then
    4585            0 :       errmsg = sjoin("fform:", itoa(fform), "is not supported in `read_dvdb` mode")
    4586            0 :       ierr = 1; return
    4587              :     end if
    4588              : 
    4589              :  case default
    4590            0 :    errmsg = sjoin("Invalid mode:", mode)
    4591        12349 :    ierr = -1; return
    4592              :  end select
    4593              : 
    4594        12349 : end function dvdb_check_fform
    4595              : !!***
    4596              : 
    4597              : !!****f* m_dvdb/dvdb_test_v1rsym
    4598              : !! NAME
    4599              : !!  dvdb_test_v1rsym
    4600              : !!
    4601              : !! FUNCTION
    4602              : !!  Debugging tool used to check whether the DFPT potentials in real space fulfill
    4603              : !!  the correct symmetries on the real space FFT mesh.
    4604              : !!
    4605              : !! INPUTS
    4606              : !!  db_path=Filename
    4607              : !!  symv1scf=1 to activate symmetrization of DFPT potentials. 0 to disable it.
    4608              : !!  comm=MPI communicator.
    4609              : !!
    4610              : !! OUTPUT
    4611              : !!  Only writing.
    4612              : !!
    4613              : !! SOURCE
    4614              : 
    4615            0 : subroutine dvdb_test_v1rsym(db_path, symv1scf, comm)
    4616              : 
    4617              : !Arguments ------------------------------------
    4618              :  character(len=*),intent(in) :: db_path
    4619              :  integer,intent(in) :: symv1scf, comm
    4620              : 
    4621              : !Local variables-------------------------------
    4622              : !scalars
    4623              :  integer,parameter :: rfmeth2=2, syuse0=0, gpu_option0 = 0
    4624              :  integer :: iqpt,idir,ipert,nsym1,cplex,v1pos, isym,nfft,ifft,ifft_rot,ispden
    4625              :  real(dp) :: max_err,re,im,vre,vim !,pre,pim
    4626              :  character(len=500) :: msg
    4627              :  logical :: isok
    4628            0 :  type(dvdb_t),target :: db
    4629              :  type(crystal_t),pointer :: cryst
    4630              : !arrays
    4631              :  integer :: ngfft(18)
    4632            0 :  integer,allocatable :: symafm1(:),symrel1(:,:,:),irottb(:,:)
    4633              :  real(dp) :: qpt(3)
    4634            0 :  real(dp),allocatable :: tnons1(:,:),v1scf(:,:)
    4635              : ! *************************************************************************
    4636              : 
    4637            0 :  call db%init(db_path, gpu_option0, comm)
    4638            0 :  db%debug = .True.
    4639            0 :  db%symv1 = symv1scf
    4640            0 :  call db%print([std_out], "", 0)
    4641              :  !call db%list_perts([-1,-1,-1], npert_miss)
    4642              : 
    4643            0 :  call ngfft_seq(ngfft, db%ngfft3_v1(:,1))
    4644            0 :  nfft = product(ngfft(1:3))
    4645            0 :  call db%open_read(ngfft, comm)
    4646              : 
    4647            0 :  cryst => db%cryst
    4648            0 :  ABI_MALLOC(symafm1, (cryst%nsym))
    4649            0 :  ABI_MALLOC(symrel1, (3,3,cryst%nsym))
    4650            0 :  ABI_MALLOC(tnons1, (3,cryst%nsym))
    4651              : 
    4652            0 :  do iqpt=1,db%nqpt
    4653            0 :    qpt = db%qpts(:, iqpt)
    4654            0 :    do ipert=1,db%natom
    4655            0 :      do idir=1,3
    4656            0 :        v1pos = db%pos_dpq(idir, ipert, iqpt); if (v1pos == 0) cycle
    4657              : 
    4658              :        ! Determines the set of symmetries that leaves the perturbation invariant.
    4659              :        call littlegroup_pert(cryst%gprimd,idir,cryst%indsym,dev_null,ipert,cryst%natom,cryst%nsym,nsym1,rfmeth2,&
    4660              :          cryst%symafm,symafm1,db%symq_table(:,:,:,iqpt),cryst%symrec,cryst%symrel,symrel1,syuse0,cryst%tnons,&
    4661            0 :          tnons1,unit=dev_null)
    4662              : 
    4663            0 :        cplex = db%cplex_v1(v1pos)
    4664            0 :        ngfft(1:3) = db%ngfft3_v1(:, v1pos)
    4665            0 :        nfft = product(ngfft(:3))
    4666            0 :        ABI_MALLOC(v1scf, (cplex*nfft, db%nspden))
    4667              : 
    4668            0 :        if (db%read_onev1(idir, ipert, iqpt, cplex, nfft, ngfft, v1scf, msg) /= 0) then
    4669            0 :          ABI_ERROR(msg)
    4670              :        end if
    4671              : 
    4672            0 :        ABI_MALLOC(irottb, (nfft,nsym1))
    4673            0 :        call rotate_fft_mesh(nsym1,symrel1,tnons1,ngfft,irottb,isok)
    4674            0 :        if (.not. isok) then
    4675            0 :          ABI_WARNING("Real space FFT mesh is not compatible with symmetries!")
    4676              :        end if
    4677              : 
    4678            0 :        max_err = zero
    4679            0 :        do isym=1,nsym1
    4680            0 :          do ispden=1,db%nspden
    4681            0 :            do ifft=1,nfft
    4682            0 :              ifft_rot = irottb(ifft, isym)
    4683              :              !pre =  cos(two_pi * dot_product(qpt, tnons1(:,isym)))
    4684              :              !pim = -sin(two_pi * dot_product(qpt, tnons1(:,isym)))
    4685            0 :              if (cplex == 2) then
    4686            0 :                re = v1scf(2*ifft_rot-1, ispden)
    4687            0 :                im = v1scf(2*ifft_rot  , ispden)
    4688              :                !vre = re * pre - im * pim
    4689              :                !vim = re * pim + im * pre
    4690            0 :                vre = re; vim = im
    4691              : 
    4692            0 :                re = v1scf(2*ifft-1, ispden) - vre
    4693            0 :                im = v1scf(2*ifft  , ispden) - vim
    4694              :              else
    4695            0 :                re = v1scf(ifft, ispden) - v1scf(ifft_rot, ispden)
    4696            0 :                im = zero
    4697              :              end if
    4698              :              !if (sqrt(re**2 + im**2) > tol6) write(std_out,*)"ifft,isym,err: ",ifft,isym,sqrt(re**2 + im**2)
    4699            0 :              max_err = max(max_err, sqrt(re**2 + im**2))
    4700              :            end do
    4701              :          end do
    4702              :        end do
    4703            0 :        if (nsym1>1) then
    4704            0 :          write(std_out,"(3(a,i2),a,i2,a,es16.8)")"For iqpt= ",iqpt,&
    4705            0 :          ", idir= ",idir,", ipert= ",ipert,", nsym= ",nsym1,", max_err= ",max_err
    4706              :        end if
    4707              : 
    4708            0 :        ABI_FREE(irottb)
    4709            0 :        ABI_FREE(v1scf)
    4710              :      end do
    4711              :    end do
    4712              : 
    4713              :  end do ! iqpt
    4714              : 
    4715            0 :  ABI_FREE(symafm1)
    4716            0 :  ABI_FREE(symrel1)
    4717            0 :  ABI_FREE(tnons1)
    4718              : 
    4719            0 :  call db%free()
    4720              : 
    4721            0 : end subroutine dvdb_test_v1rsym
    4722              : !!***
    4723              : 
    4724              : !----------------------------------------------------------------------
    4725              : 
    4726              : !!****f* m_dvdb/dvdb_test_v1complete
    4727              : !! NAME
    4728              : !!  dvdb_test_v1complete
    4729              : !!
    4730              : !! FUNCTION
    4731              : !!  Debugging tool used to test the symmetrization of the DFPT potentials.
    4732              : !!  Assumes DVDB file containing all 3*natom perturbations (either generated with nsym == 1 or
    4733              : !!  via other specialized variables e.g. prepgkk)
    4734              : !!
    4735              : !! INPUTS
    4736              : !!  db_path=Filename of the DVDB file.
    4737              : !!  symv1scf=1 to activate symmetrization of DFPT potentials. 0 ti disable it.
    4738              : !!  dump_path=File used to dump potentials (empty string to disable output)
    4739              : !!  comm=MPI communicator.
    4740              : !!
    4741              : !! OUTPUT
    4742              : !!  Only writing.
    4743              : !!
    4744              : !! SOURCE
    4745              : 
    4746            0 : subroutine dvdb_test_v1complete(dvdb_filepath, symv1scf, dump_path, comm)
    4747              : 
    4748              : !Arguments ------------------------------------
    4749              :  character(len=*),intent(in) :: dvdb_filepath,dump_path
    4750              :  integer,intent(in) :: symv1scf, comm
    4751              : 
    4752              : !Local variables-------------------------------
    4753              : !scalars
    4754              :  integer,parameter :: master = 0, gpu_option0 = 0
    4755              :  integer :: iqpt,pcase,idir,ipert,cplex,nfft,ispden,timerev_q,ifft,unt,my_rank, ncid
    4756              :  integer :: i1,i2,i3,n1,n2,n3,id1,id2,id3,cnt, npert_miss
    4757              :  integer :: ncerr
    4758              :  character(len=500) :: msg
    4759              :  type(crystal_t),pointer :: cryst
    4760            0 :  type(dvdb_t),target :: dvdb
    4761              :  type(vdiff_t) :: vd
    4762              : !arrays
    4763              :  integer :: ngfft(18), rfdir(3)
    4764            0 :  integer,allocatable :: pflag(:,:), pertsy(:,:),rfpert(:),symq(:,:,:)
    4765              :  real(dp) :: qpt(3)
    4766            0 :  real(dp),allocatable :: file_v1scf(:,:,:,:),symm_v1scf(:,:,:,:), work2(:,:,:,:)
    4767              : ! *************************************************************************
    4768              : 
    4769            0 :  my_rank = xmpi_comm_rank(comm)
    4770              : 
    4771            0 :  call dvdb%init(dvdb_filepath, gpu_option0, comm)
    4772            0 :  dvdb%debug = .false.
    4773            0 :  dvdb%symv1 = symv1scf
    4774            0 :  call dvdb%print([std_out], "", 0)
    4775            0 :  call dvdb%list_perts([-1,-1,-1], npert_miss)
    4776              : 
    4777            0 :  call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1))
    4778            0 :  nfft = product(ngfft(1:3))
    4779            0 :  call dvdb%open_read(ngfft, comm)
    4780              : 
    4781            0 :  cryst => dvdb%cryst
    4782              : 
    4783            0 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    4784            0 :  id1 = n1/2+2; id2 = n2/2+2; id3 = n3/2+2
    4785              : 
    4786            0 :  ABI_MALLOC(pflag, (3, dvdb%natom))
    4787              : 
    4788              :  ! Initialize the list of perturbations rfpert and rdfir
    4789              :  ! WARNING: Only phonon perturbations are considered for the time being.
    4790            0 :  ABI_MALLOC(rfpert,(dvdb%mpert))
    4791            0 :  rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1
    4792            0 :  ABI_MALLOC(symq, (4,2,cryst%nsym))
    4793            0 :  ABI_MALLOC(pertsy, (3,dvdb%mpert))
    4794              : 
    4795            0 :  unt = -1; ncid = nctk_noid
    4796            0 :  if (len_trim(dump_path) /= 0 .and. my_rank == master) then
    4797            0 :    write(std_out,"(a)")sjoin("Will write potentials to:", dump_path)
    4798            0 :    if (endswith(dump_path, ".nc")) then
    4799            0 :      NCF_CHECK(nctk_open_create(ncid, dump_path, xmpi_comm_self))
    4800            0 :      NCF_CHECK(dvdb%cryst%ncwrite(ncid))
    4801              :      ncerr = nctk_def_dims(ncid, [&
    4802              :        nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("nfft", nfft), nctkdim_t("nspden", dvdb%nspden), &
    4803              :        nctkdim_t("natom3", cryst%natom * 3), nctkdim_t("mpert", dvdb%mpert), nctkdim_t("nqpt", dvdb%nqpt)], &
    4804            0 :        defmode=.True.)
    4805            0 :      NCF_CHECK(ncerr)
    4806            0 :      NCF_CHECK(nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "symv1scf"]))
    4807            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("qpts", "dp", "three, nqpt")))
    4808            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("origin_v1scf", "dp", "two, nfft, nspden, natom3, nqpt")))
    4809            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("recons_v1scf", "dp", "two, nfft, nspden, natom3, nqpt")))
    4810            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("pertsy_qpt", "int", "three, mpert, nqpt")))
    4811            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("ngfft", "int", "three")))
    4812            0 :      NCF_CHECK(nctk_set_datamode(ncid))
    4813              :      ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
    4814            0 :        "symv1scf"], [symv1scf])
    4815            0 :      NCF_CHECK(ncerr)
    4816            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpts"), dvdb%qpts))
    4817            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngfft"), ngfft(1:3)))
    4818              :    else
    4819            0 :      if (open_file(dump_path, msg, newunit=unt, action="write", status="unknown", form="formatted") /= 0) then
    4820            0 :        ABI_ERROR(msg)
    4821              :      end if
    4822              :    end if
    4823              :  end if
    4824              : 
    4825            0 :  ABI_CALLOC(work2, (2, nfft, dvdb%nspden, dvdb%natom3))
    4826              : 
    4827              :  ! loop over the q-points available in the dvdb (likely qpts in the IBZ)
    4828              :  ! For each q-point, use symmetries to reconstruct all 3*natom perts for the independent ones
    4829              :  ! and compare with the corresponding results available in the DVDB file
    4830              : 
    4831            0 :  do iqpt=1,dvdb%nqpt
    4832            0 :    qpt = dvdb%qpts(:,iqpt)
    4833              : 
    4834              :    ! Examine the symmetries of the q wavevector
    4835            0 :    call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,timerev_q,prtvol=dvdb%prtvol)
    4836              : 
    4837              :    ! Determine the symmetrical perturbations. Meaning of pertsy:
    4838              :    !    0 for non-target perturbations
    4839              :    !    1 for basis perturbations
    4840              :    !   -1 for perturbations that can be found from basis perturbations
    4841              :    call irreducible_set_pert(cryst%indsym,dvdb%mpert,cryst%natom,cryst%nsym,&
    4842            0 :      pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel)
    4843              : 
    4844              :    ! Read all potentials (here we assume that all perturbations are available in the DVDB)
    4845            0 :    call dvdb%readsym_allv1(iqpt, cplex, nfft, ngfft, file_v1scf, dvdb%comm)
    4846              : 
    4847              :    ! Copy basis perturbations in symm_v1scf and set pflag
    4848            0 :    ABI_MALLOC(symm_v1scf, (cplex, nfft, dvdb%nspden, dvdb%natom3))
    4849            0 :    symm_v1scf = huge(one); pflag = 0
    4850            0 :    do pcase=1,3*dvdb%cryst%natom
    4851            0 :      idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1
    4852            0 :      if (pertsy(idir, ipert) == 1) then
    4853            0 :        symm_v1scf(:,:,:,pcase) = file_v1scf(:,:,:,pcase)
    4854            0 :        pflag(idir,ipert) = 1
    4855              :      end if
    4856              :    end do
    4857              : 
    4858              :    ! Complete potentials by symmetry.
    4859            0 :    call v1phq_complete(cryst,qpt,ngfft,cplex,nfft,dvdb%nspden,dvdb%nsppol,dvdb%mpi_enreg,dvdb%symv1,pflag,symm_v1scf)
    4860              : 
    4861            0 :    if (ncid /= nctk_noid) then
    4862            0 :      work2 = zero
    4863            0 :      if (cplex == 1) work2(1,:,:,:) = file_v1scf(1,:,:,:)
    4864            0 :      if (cplex == 2) work2 = file_v1scf
    4865            0 :      ncerr = nf90_put_var(ncid, nctk_idname(ncid, "origin_v1scf"), work2, start=[1,1,1,1,iqpt])
    4866            0 :      NCF_CHECK(ncerr)
    4867            0 :      if (cplex == 1) work2(1,:,:,:) = symm_v1scf(1,:,:,:)
    4868            0 :      if (cplex == 2) work2 = symm_v1scf
    4869            0 :      ncerr = nf90_put_var(ncid, nctk_idname(ncid, "recons_v1scf"), work2, start=[1,1,1,1,iqpt])
    4870            0 :      NCF_CHECK(ncerr)
    4871            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "pertsy_qpt"), pertsy, start=[1,1,iqpt]))
    4872              :    end if
    4873              : 
    4874              :    ! Compare potentials.
    4875            0 :    do pcase=1,3*cryst%natom
    4876            0 :      idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1
    4877            0 :      if (pflag(idir,ipert) /= 2) cycle
    4878            0 :      cnt = cnt+1
    4879              : 
    4880            0 :      do ispden=1,dvdb%nspden
    4881              :        !write(std_out,"(5(a,i0),3a,es12.4)")"For cnt: ",cnt ,", iqpt: ", iqpt, ", idir: ", idir, &
    4882              :        !        ", ipert: ", ipert, ", ispden: ", ispden, ", qpt: ", trim(ktoa(qpt)) ,", max_err: ", &
    4883              :        !        maxval(abs(file_v1scf(:,:,ispden,pcase) - symm_v1scf(:,:,ispden,pcase)))
    4884              :        !write(std_out,"(a,es10.3)")" max(abs(f1-f2))", maxval(abs(file_v1scf(:,:,ispden,pcase) - symm_v1scf(:,:,ispden,pcase)))
    4885            0 :        call vd%eval(cplex,nfft,file_v1scf(:,:,ispden,pcase),symm_v1scf(:,:,ispden,pcase),cryst%ucvol, unit=std_out)
    4886              : 
    4887              :        ! Debug: write potentials to file.
    4888            0 :        if (unt /= -1) then
    4889            0 :          write(unt,*)"# count:", cnt
    4890            0 :          write(unt,*)"# q-point:", trim(ktoa(qpt)), ", iqpt: ", trim(itoa(iqpt))
    4891            0 :          write(unt,*)"# idir: ",idir,", ipert: ",ipert,", ispden:", ispden
    4892            0 :          write(unt,*)"# file_v1scf, symmetrized_v1scf, diff"
    4893            0 :          if (cplex == 1) then
    4894            0 :            do i3=1,n3
    4895            0 :              do i2=1,n2
    4896            0 :                do i1=1,n1
    4897            0 :                  ifft = i1+n1*((i2-1)+n2*(i3-1))
    4898              :                  write(unt,"(3i3,3(es12.4,2x))") &
    4899            0 :                    i1,i2,i3, &
    4900            0 :                    file_v1scf(1,ifft,ispden,pcase), symm_v1scf(1,ifft,ispden,pcase), &
    4901            0 :                    file_v1scf(1,ifft,ispden,pcase) - symm_v1scf(1,ifft,ispden,pcase)
    4902              :                end do
    4903              :              end do
    4904              :            end do
    4905              :          else
    4906            0 :            do i3=1,n3
    4907            0 :              do i2=1,n2
    4908            0 :                do i1=1,n1
    4909            0 :                  ifft = i1+n1*((i2-1)+n2*(i3-1))
    4910              :                  write(unt, "(3i3,6(es12.4,2x))") &
    4911            0 :                    i1,i2,i3, &
    4912            0 :                    file_v1scf(1,ifft,ispden,pcase), symm_v1scf(1,ifft,ispden,pcase),  &
    4913            0 :                    file_v1scf(1,ifft,ispden,pcase) - symm_v1scf(1,ifft,ispden,pcase), &
    4914            0 :                    file_v1scf(2,ifft,ispden,pcase), symm_v1scf(2,ifft,ispden,pcase),  &
    4915            0 :                    file_v1scf(2,ifft,ispden,pcase) - symm_v1scf(2,ifft,ispden,pcase)
    4916              :                end do
    4917              :              end do
    4918              :            end do
    4919              :          end if
    4920            0 :          write(unt,*)
    4921            0 :          write(unt,*)
    4922              :        end if
    4923              : 
    4924              :      end do
    4925              :      !write(std_out,*)""
    4926              :    end do
    4927              : 
    4928            0 :    ABI_FREE(symm_v1scf)
    4929            0 :    ABI_FREE(file_v1scf)
    4930              :  end do
    4931              : 
    4932            0 :  ABI_FREE(work2)
    4933            0 :  ABI_FREE(pflag)
    4934            0 :  ABI_FREE(rfpert)
    4935            0 :  ABI_FREE(symq)
    4936            0 :  ABI_FREE(pertsy)
    4937              : 
    4938            0 :  call dvdb%free()
    4939              : 
    4940            0 :  if (unt /= -1) close(unt)
    4941            0 :  if (ncid /= nctk_noid) then
    4942            0 :    NCF_CHECK(nf90_close(ncid))
    4943              :  end if
    4944              : 
    4945            0 : end subroutine dvdb_test_v1complete
    4946              : !!***
    4947              : 
    4948              : !----------------------------------------------------------------------
    4949              : 
    4950              : !!****f* m_dvdb/dvdb_write_v1qavg
    4951              : !! NAME
    4952              : !!  dvdb_write_v1qavg
    4953              : !!
    4954              : !! FUNCTION
    4955              : !!  Computes the average over the unit cell of the periodic part of the DFPT potentials
    4956              : !!  as a function of the q-point and the corresponding quantity obtained with the model for the LR part.
    4957              : !!  Results are stored in the V1QAVG netcdf file. Two options are available:
    4958              : !!
    4959              : !!  eph_task = -15 --> Use list of q-points found in the DVDB file. Mainly used to plot the average
    4960              : !!    along a q-path. The procedure required to generate a DVDB with a q-path is rather lengthy
    4961              : !!    as it requires several phonon calculations with WKQ followed by a merge of the POT files.
    4962              : !!
    4963              : !!  eph_task = +15 --> Assume DVDB file with q-mesh (dvdb_ngqpt), use Fourier interpolation
    4964              : !!    to interpolate potentials along the path specified by ph_qpath and ph_nqpath.
    4965              : !!
    4966              : !! INPUTS
    4967              : !!  dtset<dataset_type>= Input variables.
    4968              : !!  out_ncpath=Filename for output netcdf file.
    4969              : !!
    4970              : !! OUTPUT
    4971              : !!  Only writing.
    4972              : !!
    4973              : !! SOURCE
    4974              : 
    4975            2 : subroutine dvdb_write_v1qavg(dvdb, dtset, out_ncpath)
    4976              : 
    4977              : !Arguments ------------------------------------
    4978              :  class(dvdb_t),target,intent(inout) :: dvdb
    4979              :  type(dataset_type),target,intent(in) :: dtset
    4980              :  character(len=*),intent(in) :: out_ncpath
    4981              : 
    4982              : !Local variables-------------------------------
    4983              : !scalars
    4984              :  integer,parameter :: master = 0
    4985              :  integer :: nfft, iq, cplex, ispden, comm_rpt, my_rank, idir, ipert, ipc, imyp
    4986              :  integer :: n1, n2, n3, unt, this_nqpt, interpolated
    4987              :  integer :: i1, i2, i3, ifft, ig, ngsmall, ii, qptopt
    4988              :  integer :: ncid, ncerr
    4989              :  real(dp) :: gsq_max, g2
    4990              :  !type(vdiff_t) :: vd_max
    4991              :  logical :: write_v1r
    4992              :  character(len=500) :: msg
    4993              :  character(len=fnlen) :: dump_path
    4994              : !arrays
    4995              :  integer :: ngfft(18), units(2)
    4996            2 :  integer, allocatable :: gfft(:,:),ig2ifft(:), gsmall(:,:)
    4997              :  real(dp) :: dvdb_qdamp(1)
    4998              :  real(dp) :: vals2(2)
    4999            2 :  real(dp),pointer :: this_qpts(:,:)
    5000            2 :  real(dp),allocatable :: file_v1r(:,:,:,:),long_v1r(:,:,:,:),tmp_v1r(:,:,:,:)
    5001            2 :  real(dp),allocatable :: maxw(:,:), all_rpt(:,:), all_rmod(:), workg(:,:), work_gsmall(:,:)
    5002              : ! *************************************************************************
    5003              : 
    5004            4 :  my_rank = xmpi_comm_rank(dvdb%comm)
    5005            6 :  units = [std_out, ab_out]
    5006              : 
    5007            2 :  call wrtout(units, " Computing average over the unit cell of the periodic part of the DFPT potentials", newlines=2)
    5008            4 :  call dvdb%print([std_out], "", 0)
    5009              : 
    5010              :  ! Define FFT mesh
    5011           38 :  ngfft = dvdb%ngfft
    5012            8 :  nfft = product(ngfft(1:3))
    5013            2 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    5014              : 
    5015              :  ! Get list of G-vectors in FFT mesh.
    5016            6 :  ABI_MALLOC(gfft, (3, nfft))
    5017            2 :  call get_gfft(ngfft, [zero, zero, zero], dvdb%cryst%gmet, gsq_max, gfft)
    5018            6 :  ABI_MALLOC(workg, (2, nfft))
    5019              : 
    5020              :  ! Select G-vectors in small sphere (ratio of gsq_max)
    5021            6 :  do ii=1,2
    5022            4 :    if (ii == 2) then
    5023            6 :      ABI_MALLOC(ig2ifft, (ngsmall))
    5024              :    end if
    5025            4 :    ngsmall = 0
    5026        16390 :    do ig=1,nfft
    5027              :      ! Don't include (2pi)**2 to be consistent with get_gfft
    5028       327680 :      g2 = dot_product(gfft(:,ig), matmul(dvdb%cryst%gmet, gfft(:, ig)))
    5029        16384 :      if (g2 <= gsq_max * 0.01_dp) ngsmall = ngsmall + 1
    5030        16388 :      if (ii == 2) ig2ifft(ngsmall) = ig
    5031              :    end do
    5032              :  end do
    5033            2 :  write(std_out, *)"Found ngsmall", ngsmall
    5034              : 
    5035              :  !call ig2fft_sphere(dvdb%cryst%gmet, gfft, ig2ifft)
    5036            6 :  ABI_MALLOC(gsmall, (3, ngsmall))
    5037           56 :  do ig=1,ngsmall
    5038          218 :    gsmall(:, ig) = gfft(:, ig2ifft(ig))
    5039              :  end do
    5040            6 :  ABI_MALLOC(work_gsmall, (2, ngsmall))
    5041              : 
    5042           10 :  ABI_MALLOC(long_v1r, (2, nfft, dvdb%nspden, dvdb%my_npert))
    5043            8 :  ABI_MALLOC(file_v1r, (2, nfft, dvdb%nspden, dvdb%my_npert))
    5044              : 
    5045            2 :  unt = -1; dump_path = ""
    5046              :  !dump_path = "V1QAVG.dat"
    5047            2 :  if (len_trim(dump_path) /= 0 .and. my_rank == master) then
    5048            0 :    if (open_file(dump_path, msg, newunit=unt, action="write", status="unknown", form="formatted") /= 0) then
    5049            0 :      ABI_ERROR(msg)
    5050              :    end if
    5051            0 :    write(std_out,"(a)")sjoin(" Will write potentials in text format to:", dump_path)
    5052              :  end if
    5053              : 
    5054              :  ! Select list of q-points depending on eph_task (either from DVDB file or interpolated)
    5055            2 :  write_v1r = .False.
    5056            2 :  if (dtset%eph_task == -15) then
    5057            1 :    call wrtout(units, " Using list of q-points found in the DVDB file")
    5058            1 :    this_nqpt = dvdb%nqpt
    5059            1 :    this_qpts => dvdb%qpts
    5060            1 :    interpolated = 0
    5061              : 
    5062            1 :  else if (dtset%eph_task == +15) then
    5063            1 :    msg = sjoin(" Using list of q-points specified by ph_qpath with ", itoa(dtset%ph_nqpath), "qpoints")
    5064            1 :    call wrtout(units, msg)
    5065            1 :    ABI_CHECK(dtset%ph_nqpath > 0, "When eph_task = +15, ph_qpath must be given in input.")
    5066            1 :    this_nqpt = dtset%ph_nqpath
    5067            1 :    this_qpts => dtset%ph_qpath(:, 1:this_nqpt)
    5068            1 :    comm_rpt = xmpi_comm_self
    5069            1 :    qptopt = dtset%kptopt; if (dtset%qptopt /= 0) qptopt = dtset%qptopt
    5070            1 :    call dvdb%ftinterp_setup(dtset%ddb_ngqpt, qptopt, 1, dtset%ddb_shiftq, nfft, ngfft, comm_rpt)
    5071            1 :    interpolated = 1
    5072            1 :    write_v1r = dtset%prtpot > 0
    5073              :  else
    5074            0 :    ABI_ERROR(sjoin("Invalid value for eph_task:", itoa(dtset%eph_task)))
    5075              :  end if
    5076              : 
    5077            2 :  call wrtout(units, sjoin(ch10, "- Results stored in: ", out_ncpath))
    5078            2 :  call wrtout(units, " Use `abiopen.py out_V1QAVG.nc -e` to visualize results")
    5079              : 
    5080            2 :  if (my_rank == master) then
    5081            2 :    NCF_CHECK(nctk_open_create(ncid, out_ncpath, xmpi_comm_self))
    5082            2 :    NCF_CHECK(dvdb%cryst%ncwrite(ncid))
    5083              :    ncerr = nctk_def_dims(ncid, [ &
    5084              :      nctkdim_t("nspden", dvdb%nspden), nctkdim_t("natom", dvdb%natom3 / 3), nctkdim_t("nqpt", this_nqpt), &
    5085           12 :      nctkdim_t("natom3", dvdb%natom3), nctkdim_t("ngsmall", ngsmall)], defmode=.True.)
    5086            2 :    NCF_CHECK(ncerr)
    5087              : 
    5088            2 :    if (interpolated == 1) then
    5089              :      ! Define arrays for Max_r |W(R, r)|
    5090            3 :      NCF_CHECK(nctk_def_dims(ncid, [nctkdim_t("nrpt", dvdb%nrtot), nctkdim_t("nfft", nfft)]))
    5091              :      ncerr = nctk_def_arrays(ncid, [ &
    5092              :         nctkarr_t("ngqpt", "int", "three"), nctkarr_t("rpt", "dp", "three, nrpt"), nctkarr_t("rmod", "dp", "nrpt"), &
    5093              :         nctkarr_t("ngfft", "int", "three"), &
    5094              :         nctkarr_t("maxw", "dp", "nrpt, natom3") &
    5095            6 :      ])
    5096            1 :      NCF_CHECK(ncerr)
    5097              :    end if
    5098              : 
    5099              :    ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
    5100           10 :      "symdynmat", "symv1scf", "dvdb_add_lr", "interpolated"])
    5101            2 :    NCF_CHECK(ncerr)
    5102              :    ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
    5103           12 :      "has_dielt", "has_zeff", "has_quadrupoles", "has_efield", "dvdb_add_lr"])
    5104            2 :    NCF_CHECK(ncerr)
    5105            4 :    NCF_CHECK(nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "qdamp"]))
    5106              :    ncerr = nctk_def_arrays(ncid, [ &
    5107              :      nctkarr_t("v1scf_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5108              :      nctkarr_t("v1lr_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5109              :      nctkarr_t("v1scfmlr_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5110              :      nctkarr_t("v1scfmlr_abs_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5111              :      nctkarr_t("v1scf_abs_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5112              :      nctkarr_t("v1lr_abs_avg", "dp", "two, nspden, three, natom, nqpt"), &
    5113              :      nctkarr_t("gsmall", "int", "three, ngsmall"), &
    5114              :      nctkarr_t("v1scf_gsmall", "dp", "two, ngsmall, nspden, three, natom, nqpt"), &
    5115              :      nctkarr_t("v1lr_gsmall", "dp", "two, ngsmall, nspden, three, natom, nqpt"), &
    5116              :      nctkarr_t("qpoints", "dp", "three, nqpt") &
    5117           22 :    ])
    5118            2 :    NCF_CHECK(ncerr)
    5119              : 
    5120            2 :    if (write_v1r) then
    5121              :      ncerr = nctk_def_arrays(ncid, [ &
    5122              :        nctkarr_t("v1r_interpolated", "dp", "two, nfft, nspden, natom3"), &
    5123              :        nctkarr_t("v1r_lrmodel", "dp", "two, nfft, nspden, natom3") &
    5124            0 :       ])
    5125            0 :      NCF_CHECK(ncerr)
    5126              :    end if
    5127              : 
    5128            2 :    NCF_CHECK(nctk_set_datamode(ncid))
    5129            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpoints"), this_qpts))
    5130              :    ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
    5131              :        "symdynmat", "symv1scf", "dvdb_add_lr", "interpolated"], &
    5132           18 :        [dtset%symdynmat, dvdb%symv1, dtset%dvdb_add_lr, interpolated])
    5133            2 :    NCF_CHECK(ncerr)
    5134              :    ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
    5135              :      "has_dielt", "has_zeff", "has_quadrupoles", "has_efield"], &
    5136           18 :      l2int([dvdb%has_dielt, dvdb%has_zeff, dvdb%has_quadrupoles, dvdb%has_efield]))
    5137            2 :    NCF_CHECK(ncerr)
    5138            4 :    dvdb_qdamp = dvdb%qdamp
    5139            4 :    NCF_CHECK(nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: "qdamp"], dvdb_qdamp))
    5140            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "gsmall"), gsmall))
    5141              :  end if
    5142              : 
    5143           10 :  do iq=1,this_nqpt
    5144              : 
    5145            8 :    if (interpolated == 0) then
    5146            3 :      call wrtout(std_out, sjoin(" Treating qpt:", ktoa(this_qpts(:,iq))))
    5147              : 
    5148              :      ! Read data from DVDB file, reconstruct all 3*natom perturbations in tmp_v1r.
    5149            3 :      call dvdb%readsym_allv1(dvdb%findq(this_qpts(:, iq)), cplex, nfft, ngfft, tmp_v1r, xmpi_comm_self)
    5150              : 
    5151              :      ! Transfer data to file_v1r taking into account my_npert
    5152           21 :      do imyp=1,dvdb%my_npert
    5153           18 :        ipc = dvdb%my_pinfo(3, imyp)
    5154           21 :        if (cplex == 1) then
    5155        24588 :          file_v1r(1,:,:,imyp) = tmp_v1r(1,:,:,ipc)
    5156        24588 :          file_v1r(2,:,:,imyp) = zero
    5157              :        else
    5158       147480 :          file_v1r(:,:,:,imyp) = tmp_v1r(:,:,:,ipc)
    5159              :        end if
    5160              :      end do
    5161            3 :      ABI_FREE(tmp_v1r)
    5162              : 
    5163              :    else
    5164              :      ! Interpolate my_npert potentials for this q-point.
    5165            5 :      call wrtout(std_out, sjoin(" Interpolating qpt:", ktoa(this_qpts(:,iq))))
    5166            5 :      call dvdb%ftinterp_qpt(this_qpts(:, iq), nfft, ngfft, file_v1r, comm_rpt) !, add_lr=?)
    5167            5 :      cplex = 2
    5168              :    end if
    5169              : 
    5170              :    ! Compute the periodic part of the LR term (note add_qphase = 0 because we want the periodic part)
    5171           56 :    do imyp=1,dvdb%my_npert
    5172           48 :      idir = dvdb%my_pinfo(1, imyp); ipert = dvdb%my_pinfo(2, imyp); ipc = dvdb%my_pinfo(3, imyp)
    5173          104 :      do ispden=1,min(dvdb%nspden, 2)
    5174           96 :        call dvdb%get_v1r_long_range(this_qpts(:,iq), idir, ipert, nfft, ngfft, long_v1r(:,:,ispden,imyp), add_qphase=0)
    5175              :      end do
    5176              :    end do
    5177              : 
    5178              :    ! Compute average and write to file.
    5179            8 :    if (my_rank /= master) cycle
    5180              : 
    5181            8 :    if (write_v1r .and. iq == 1) then
    5182            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_interpolated"), file_v1r))
    5183            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_lrmodel"), long_v1r))
    5184              :    end if
    5185              : 
    5186           58 :    do imyp=1,dvdb%my_npert
    5187           48 :      idir = dvdb%my_pinfo(1, imyp); ipert = dvdb%my_pinfo(2, imyp); ipc = dvdb%my_pinfo(3, imyp)
    5188          104 :      do ispden=1,dvdb%nspden
    5189              : 
    5190       393360 :        vals2 = sum(file_v1r(:,:,ispden,imyp), dim=2) / nfft
    5191              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_avg"), vals2, &
    5192          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5193           48 :        NCF_CHECK(ncerr)
    5194              : 
    5195       393360 :        vals2 = sum(abs(file_v1r(:,:,ispden,imyp)), dim=2) / nfft
    5196              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_abs_avg"), vals2, &
    5197          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5198           48 :        NCF_CHECK(ncerr)
    5199              : 
    5200       393360 :        vals2 = sum(long_v1r(:,:,ispden,imyp), dim=2) / nfft
    5201              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_avg"), vals2, &
    5202          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5203           48 :        NCF_CHECK(ncerr)
    5204       393360 :        vals2 = sum(abs(long_v1r(:,:,ispden,imyp)), dim=2) / nfft
    5205              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_abs_avg"), vals2, &
    5206          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5207           48 :        NCF_CHECK(ncerr)
    5208       393360 :        vals2 = sum(file_v1r(:,:,ispden,imyp) - long_v1r(:,:,ispden,imyp), dim=2) / nfft
    5209              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scfmlr_avg"), vals2, &
    5210          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5211           48 :        NCF_CHECK(ncerr)
    5212       393360 :        vals2 = sum(abs(file_v1r(:,:,ispden,imyp) - long_v1r(:,:,ispden,imyp)), dim=2) / nfft
    5213              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scfmlr_abs_avg"), vals2, &
    5214          288 :                             start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1])
    5215           48 :        NCF_CHECK(ncerr)
    5216              : 
    5217              :        ! Compute G-components of DFPT potentials and LR model for G in small-sphere and save results to disk
    5218           48 :        call fourdp(2, workg, file_v1r(:,:,ispden,imyp), -1, dvdb%mpi_enreg, nfft, 1, ngfft, 0)
    5219         1344 :        do ig=1,ngsmall
    5220         3936 :          work_gsmall(:, ig) = workg(:, ig2ifft(ig))
    5221              :        end do
    5222              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_gsmall"), work_gsmall, &
    5223          624 :                             start=[1,1,ispden,idir,ipert,iq], count=[2,ngsmall,1,1,1,1])
    5224           48 :        NCF_CHECK(ncerr)
    5225              : 
    5226           48 :        call fourdp(2, workg, long_v1r(:,:,ispden,imyp), -1, dvdb%mpi_enreg, nfft, 1, ngfft, 0)
    5227         1344 :        do ig=1,ngsmall
    5228         3936 :          work_gsmall(:, ig) = workg(:, ig2ifft(ig))
    5229              :        end do
    5230              :        ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_gsmall"), work_gsmall, &
    5231          624 :                             start=[1,1,ispden,idir,ipert,iq], count=[2,ngsmall,1,1,1,1])
    5232           48 :        NCF_CHECK(ncerr)
    5233              : 
    5234              :        ! Debugging section.
    5235              :        !write(std_out, "(a)")"--- !DVDB_LONGRANGE_DIFF"
    5236              :        !write(std_out,"(3a)")"  qpoint: ", trim(ktoa(this_qpts(:,iq))), ","
    5237              :        !write(std_out,"(a,i0,a)")"  iq: ", iq, ","
    5238              :        !write(std_out,"(2(a,i0))")"  idir: ", idir, ", ipert:", ipert
    5239              :        !write(std_out,"(a,i0,a)")"  ispden: ", ispden, ","
    5240              :        !call call vd%eval(2, nfft, file_v1r(:,:,ispden,imyp), long_v1r(:,:,ispden,imyp), &
    5241              :        !                 dvdb%cryst%ucvol, vd_max=vd_max, unit=std_out))
    5242              :        !write(std_out,"(a)")"..."
    5243              : 
    5244              :        ! Debug: write potentials to file.
    5245           96 :        if (unt /= -1) then
    5246            0 :          write(unt,*)"# q-point:", trim(ktoa(this_qpts(:,iq))), ", iq: ", trim(itoa(iq))
    5247            0 :          write(unt,*)"# idir: ",idir,", ipert: ",ipert,", ispden:", ispden
    5248            0 :          write(unt,*)"# file_v1r, long_v1r, diff"
    5249              : 
    5250            0 :          if (cplex == 1) then
    5251            0 :            do i3=1,n3
    5252            0 :              do i2=1,n2
    5253            0 :                do i1=1,n1
    5254            0 :                  ifft = i1+n1*((i2-1)+n2*(i3-1))
    5255              :                  write(unt,"(3(i0,1x),3(es12.4,2x))") &
    5256            0 :                    i1,i2,i3, &
    5257            0 :                    file_v1r(1,ifft,ispden,imyp), long_v1r(1,ifft,ispden,imyp), &
    5258            0 :                    file_v1r(1,ifft,ispden,imyp) - long_v1r(1,ifft,ispden,imyp)
    5259              :                end do
    5260              :              end do
    5261              :            end do
    5262              :          else
    5263            0 :            do i3=1,n3
    5264            0 :              do i2=1,n2
    5265            0 :                do i1=1,n1
    5266            0 :                  ifft = i1+n1*((i2-1)+n2*(i3-1))
    5267              :                  write(unt, "(3(i0,1x),6(es12.4,2x))") &
    5268            0 :                    i1,i2,i3, &
    5269            0 :                    file_v1r(1,ifft,ispden,imyp), long_v1r(1,ifft,ispden,imyp),  &
    5270            0 :                    file_v1r(1,ifft,ispden,imyp) - long_v1r(1,ifft,ispden,imyp), &
    5271            0 :                    file_v1r(2,ifft,ispden,imyp), long_v1r(2,ifft,ispden,imyp),  &
    5272            0 :                    file_v1r(2,ifft,ispden,imyp) - long_v1r(2,ifft,ispden,imyp)
    5273              :                end do
    5274              :              end do
    5275              :            end do
    5276              :          end if
    5277            0 :          write(unt,*)
    5278            0 :          write(unt,*)
    5279              :        end if
    5280              : 
    5281              :      end do
    5282              :    end do
    5283              :    !write(std_out,*)" "
    5284              :  end do ! iq
    5285              : 
    5286            2 :  ABI_FREE(long_v1r)
    5287            2 :  ABI_FREE(file_v1r)
    5288            2 :  ABI_FREE(workg)
    5289            2 :  ABI_FREE(gfft)
    5290            2 :  ABI_FREE(ig2ifft)
    5291            2 :  ABI_FREE(gsmall)
    5292            2 :  ABI_FREE(work_gsmall)
    5293              : 
    5294            2 :  if (interpolated == 1) then
    5295              :    ! Compute max_r |W(R,r)| and write data to file.
    5296            1 :    call dvdb%get_maxw(dtset%ddb_ngqpt, all_rpt, all_rmod, maxw)
    5297            1 :    if (my_rank == master) then
    5298            1 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngqpt"), dtset%ddb_ngqpt))
    5299            1 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "rpt"), all_rpt))
    5300            1 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "rmod"), all_rmod))
    5301            1 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngfft"), ngfft(1:3)))
    5302            1 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "maxw"), maxw))
    5303              :    end if
    5304            1 :    ABI_FREE(all_rpt)
    5305            1 :    ABI_FREE(all_rmod)
    5306            1 :    ABI_FREE(maxw)
    5307              :  end if
    5308              : 
    5309            2 :  if (my_rank == master) then
    5310            2 :    NCF_CHECK(nf90_close(ncid))
    5311              :  end if
    5312              : 
    5313            4 : end subroutine dvdb_write_v1qavg
    5314              : !!***
    5315              : 
    5316              : !----------------------------------------------------------------------
    5317              : 
    5318              : !!****f* m_dvdb/dvdb_test_ftinterp
    5319              : !! NAME
    5320              : !!  dvdb_test_ftinterp
    5321              : !!
    5322              : !! FUNCTION
    5323              : !!  Debugging tool used to test the Fourier interpolation of the DFPT potentials.
    5324              : !!
    5325              : !! INPUTS
    5326              : !!  dvdb_filepath=Filename
    5327              : !!  dvdb_ngqpt(3)=Divisions of the Q-mesh reported in the DVDB file (usually equat to ddb_ngqpt)
    5328              : !!  dvdb_add_lr=0 to disable treatment of long-range part in Fourier interpolation.
    5329              : !!  qdamp=Defines exponential damping in LR potential
    5330              : !!  ddb_filepath=Path to DDB file. Used to treat LR part.
    5331              : !!  prtvol=Verbosity level.
    5332              : !!  coarse_ngqpt(3)= Coarse q-mesh used to analyze the accuracy of the FT interpolation
    5333              : !!    Must be divisor of dvdb_ngqpt. Use 0 to disable the test.
    5334              : !!  comm=MPI communicator.
    5335              : !!
    5336              : !! OUTPUT
    5337              : !!  Only writing.
    5338              : !!
    5339              : !! SOURCE
    5340              : 
    5341            0 : subroutine dvdb_test_ftinterp(dvdb_filepath, rspace_cell, symv1, dvdb_ngqpt, dvdb_add_lr, dvdb_qdamp, &
    5342              :                               ddb_filepath, prtvol, coarse_ngqpt, dump_path, comm)
    5343              : 
    5344              : !Arguments ------------------------------------
    5345              :  character(len=*),intent(in) :: dvdb_filepath, ddb_filepath, dump_path
    5346              :  integer,intent(in) :: comm, prtvol, dvdb_add_lr, rspace_cell, symv1
    5347              :  real(dp),intent(in) :: dvdb_qdamp
    5348              :  integer,intent(in) :: dvdb_ngqpt(3), coarse_ngqpt(3)
    5349              : 
    5350              : !Local variables-------------------------------
    5351              : !scalars
    5352              :  integer,parameter :: master = 0, chneut2 = 2, qptopt1 = 1, gpu_option0 = 0
    5353              :  integer :: nfft, iq, cplex, mu, ispden, comm_rpt, iblock_dielt, iblock_dielt_zeff, my_rank,  ierr
    5354              :  integer :: ncid, ncerr
    5355              :  logical :: autotest
    5356            0 :  type(dvdb_t) :: dvdb, coarse_dvdb
    5357              :  type(vdiff_t) :: vd_max, vd
    5358            0 :  type(ddb_type) :: ddb
    5359              :  character(len=fnlen) :: coarse_fname
    5360              : !arrays
    5361              :  integer :: ngfft(18)
    5362            0 :  real(dp),allocatable :: file_v1r(:,:,:,:),intp_v1r(:,:,:,:),tmp_v1r(:,:,:,:)
    5363              : ! *************************************************************************
    5364              : 
    5365            0 :  my_rank = xmpi_comm_rank(comm)
    5366              : 
    5367            0 :  write(std_out,"(a)")sjoin(" Testing Fourier interpolation of V1(r) with ngqpt:", ltoa(dvdb_ngqpt))
    5368            0 :  if (len_trim(ddb_filepath) > 0) then
    5369            0 :    write(std_out,"(a)")sjoin(" Reading Zeff and eps_inf from DDB file:", ddb_filepath)
    5370            0 :    write(std_out,"(a)")sjoin(" dvdb_add_lr set to:", itoa(dvdb_add_lr))
    5371              :  end if
    5372              : 
    5373            0 :  call dvdb%init(dvdb_filepath, gpu_option0, comm)
    5374            0 :  dvdb%debug = .False.
    5375            0 :  ABI_CHECK(any(symv1 == [0, 1, 2]), sjoin("invalid value of symv1:", itoa(symv1)))
    5376            0 :  dvdb%symv1 = symv1
    5377            0 :  dvdb%add_lr = dvdb_add_lr
    5378            0 :  dvdb%qdamp = dvdb_qdamp
    5379            0 :  dvdb%rspace_cell = rspace_cell
    5380              : 
    5381              :  !call dvdb%set_pert_distrib(sigma%comm_pert, sigma%my_pinfo, sigma%pert_table)
    5382              : 
    5383            0 :  iblock_dielt = 0; iblock_dielt_zeff = 0
    5384            0 :  if (len_trim(ddb_filepath) > 0) then
    5385            0 :    call dvdb%load_ddb(prtvol, chneut2, comm, ddb_filepath=ddb_filepath)
    5386              :  else
    5387            0 :    dvdb%add_lr = 0
    5388            0 :    ABI_WARNING("ddb_filepath was not provided --> Setting dvdb_add_lr to zero")
    5389              :  end if
    5390              : 
    5391            0 :  call dvdb%print([std_out], "", 0)
    5392              : 
    5393              :  ! Define FFT mesh for real space representation.
    5394            0 :  call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1))
    5395            0 :  nfft = product(ngfft(1:3))
    5396            0 :  call dvdb%open_read(ngfft, comm)
    5397              : 
    5398            0 :  ABI_MALLOC(intp_v1r, (2, nfft, dvdb%nspden, dvdb%natom3))
    5399            0 :  ABI_MALLOC(file_v1r, (2, nfft, dvdb%nspden, dvdb%natom3))
    5400              : 
    5401              :  ! Prepare FT interpolation.
    5402            0 :  comm_rpt = xmpi_comm_self
    5403              : 
    5404              :  ! Optionally dump ab-initio and interpolated V1(r) to a netcdf file for post-processing in python.
    5405            0 :  ncid = nctk_noid
    5406            0 :  if (len_trim(dump_path) /= 0 .and. my_rank == master) then
    5407            0 :    write(std_out,"(a)")sjoin(" Will write ab-initio and interpolated potentials to:", dump_path)
    5408            0 :    NCF_CHECK(nctk_open_create(ncid, dump_path, xmpi_comm_self))
    5409            0 :    NCF_CHECK(dvdb%cryst%ncwrite(ncid))
    5410              :    ncerr = nctk_def_dims(ncid, [ &
    5411              :      nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("nfft", nfft), nctkdim_t("nspden", dvdb%nspden), &
    5412            0 :      nctkdim_t("natom3", dvdb%natom3), nctkdim_t("nqpt", dvdb%nqpt)], defmode=.True.)
    5413            0 :    NCF_CHECK(ncerr)
    5414            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("qpts", "dp", "three, nqpt")))
    5415            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("ngfft", "int", "three")))
    5416            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("self_v1r_abinitio", "dp", "two, nfft, nspden, natom3, nqpt")))
    5417            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("self_v1r_interp", "dp", "two, nfft, nspden, natom3, nqpt")))
    5418            0 :    if (all(coarse_ngqpt /= 0)) then
    5419            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("coarse_ngqpt", "int", "three")))
    5420            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("coarse_v1r_abinitio", "dp", "two, nfft, nspden, natom3, nqpt")))
    5421            0 :      NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("coarse_v1r_interp", "dp", "two, nfft, nspden, natom3, nqpt")))
    5422              :    end if
    5423            0 :    NCF_CHECK(nctk_set_datamode(ncid))
    5424            0 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpts"), dvdb%qpts))
    5425            0 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngfft"), ngfft(1:3)))
    5426            0 :    if (all(coarse_ngqpt /= 0)) then
    5427            0 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "coarse_ngqpt"), coarse_ngqpt))
    5428              :    end if
    5429              :  end if
    5430              : 
    5431            0 :  autotest = .True.
    5432              :  if (autotest) then
    5433            0 :    call dvdb%ftinterp_setup(dvdb_ngqpt, qptopt1, 1, [zero, zero, zero], nfft, ngfft, comm_rpt)
    5434              : 
    5435              :    ! First step: Use FT interpolation to get q-points in the initial ab-initio mesh.
    5436              :    ! We should get the same result...
    5437            0 :    do iq=1,dvdb%nqpt
    5438              :      ! Read data from DVDB file and store it in file_v1r
    5439            0 :      call dvdb%readsym_allv1(dvdb%findq(dvdb%qpts(:,iq)), cplex, nfft, ngfft, tmp_v1r, comm)
    5440              : 
    5441            0 :      if (cplex == 1) then
    5442            0 :        file_v1r(1,:,:,:) = tmp_v1r(1,:,:,:)
    5443            0 :        file_v1r(2,:,:,:) = zero
    5444              :      else
    5445            0 :        file_v1r = tmp_v1r
    5446              :      end if
    5447            0 :      ABI_FREE(tmp_v1r)
    5448              : 
    5449              :      ! Interpolate data at the same q-point.
    5450            0 :      call dvdb%ftinterp_qpt(dvdb%qpts(:,iq), nfft, ngfft, intp_v1r, dvdb%comm_rpt)
    5451              : 
    5452            0 :      write(std_out,"(a)")sjoin("=== For q-point:", ktoa(dvdb%qpts(:,iq)), "===")
    5453            0 :      do mu=1,dvdb%natom3
    5454            0 :        do ispden=1,dvdb%nspden
    5455            0 :          write(std_out, "(a)")"--- !DVDB_SELF_DIFF"
    5456            0 :          write(std_out,"(3a)")"  qpoint: ", trim(ktoa(dvdb%qpts(:,iq))), ","
    5457            0 :          write(std_out,"(a,i0,a)")"  iqpt: ", iq, ","
    5458            0 :          write(std_out,"(a,i0,a)")"  iatom3: ", mu, ","
    5459            0 :          write(std_out,"(a,i0,a)")"  ispden: ", ispden, ","
    5460              :          call vd%eval(2, nfft, file_v1r(:,:,ispden,mu), intp_v1r(:,:,ispden,mu), &
    5461            0 :                       dvdb%cryst%ucvol, vd_max=vd_max, unit=std_out)
    5462            0 :          write(std_out,"(a)")"..."
    5463              :          !do ifft=1,nfft
    5464              :          !  write(std_out,*)file_v1r(1,ifft,ispden,mu),intp_v1r(1,ifft,ispden,mu),&
    5465              :          !  file_v1r(2,ifft,ispden,mu),intp_v1r(2,ifft,ispden,mu)
    5466              :          !end do
    5467              :        end do
    5468              :      end do
    5469              : 
    5470            0 :      if (ncid /= nctk_noid) then
    5471            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "self_v1r_abinitio"), file_v1r, start=[1,1,1,1,iq]))
    5472            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "self_v1r_interp"), intp_v1r, start=[1,1,1,1,iq]))
    5473              :      end if
    5474              : 
    5475            0 :      write(std_out,*)" "
    5476              :    end do ! iq
    5477              : 
    5478            0 :    write(std_out, "(/, a)")" Max values over q-points and perturbations"
    5479            0 :    call vd_max%print()
    5480            0 :    ABI_FREE(dvdb%wsr)
    5481              :  end if
    5482              : 
    5483              :  ! Now downsample the q-mesh, build real-space representation with coarse q-mesh and
    5484              :  ! compare with ab-intio values in the initial dvdb.
    5485            0 :  if (all(coarse_ngqpt /= 0)) then
    5486            0 :    write(std_out, "(/, 2a)")" Downsampling Q-mesh using coarse_ngqpt:", trim(ltoa(coarse_ngqpt))
    5487              : 
    5488            0 :    coarse_fname = strcat(dvdb_filepath, "_COARSE")
    5489            0 :    call dvdb%qdownsample(coarse_fname, qptopt1, coarse_ngqpt, comm)
    5490              : 
    5491            0 :    call coarse_dvdb%init(coarse_fname, gpu_option0, comm)
    5492            0 :    call coarse_dvdb%open_read(ngfft, comm)
    5493              :    !call coarse_dvdb%set_pert_distrib(sigma%comm_pert, sigma%my_pinfo, sigma%pert_table)
    5494              : 
    5495            0 :    coarse_dvdb%debug = dvdb%debug
    5496            0 :    coarse_dvdb%symv1 = dvdb%symv1
    5497            0 :    coarse_dvdb%add_lr = dvdb%add_lr
    5498            0 :    coarse_dvdb%has_dielt = dvdb%has_dielt
    5499            0 :    coarse_dvdb%has_zeff = dvdb%has_zeff
    5500            0 :    coarse_dvdb%has_quadrupoles = dvdb%has_quadrupoles
    5501            0 :    coarse_dvdb%has_efield = dvdb%has_efield
    5502            0 :    coarse_dvdb%dielt = dvdb%dielt
    5503            0 :    coarse_dvdb%zeff = dvdb%zeff
    5504            0 :    coarse_dvdb%zeff_raw = dvdb%zeff_raw
    5505            0 :    coarse_dvdb%qstar = dvdb%qstar
    5506            0 :    coarse_dvdb%qdamp = dvdb%qdamp
    5507              :    !call coarse_dvdb%print()
    5508              : 
    5509              :    ! Prepare FT interpolation using coarse q-mesh.
    5510            0 :    call coarse_dvdb%ftinterp_setup(coarse_ngqpt, qptopt1, 1, [zero, zero, zero], nfft, ngfft, comm_rpt)
    5511              : 
    5512            0 :    do iq=1,dvdb%nqpt
    5513              :      ! Read data from DVDB file and store it in file_v1r
    5514            0 :      call dvdb%readsym_allv1(dvdb%findq(dvdb%qpts(:,iq)), cplex, nfft, ngfft, tmp_v1r, comm)
    5515              : 
    5516            0 :      if (cplex == 1) then
    5517            0 :        file_v1r(1,:,:,:) = tmp_v1r(1,:,:,:)
    5518            0 :        file_v1r(2,:,:,:) = zero
    5519              :      else
    5520            0 :        file_v1r = tmp_v1r
    5521              :      end if
    5522            0 :      ABI_FREE(tmp_v1r)
    5523              : 
    5524              :      ! Interpolate data at the same q-point using the coarse Q-mesh
    5525            0 :      call coarse_dvdb%ftinterp_qpt(dvdb%qpts(:,iq), nfft, ngfft, intp_v1r, dvdb%comm_rpt)
    5526              : 
    5527            0 :      write(std_out,"(a)")sjoin("=== For COARSE q-point:", ktoa(dvdb%qpts(:,iq)), "===")
    5528            0 :      do mu=1,dvdb%natom3
    5529            0 :        do ispden=1,dvdb%nspden
    5530            0 :          write(std_out, "(a)")"--- !DVDB_COARSE_DIFF"
    5531            0 :          write(std_out,"(3a)")"  qpoint: ", trim(ktoa(dvdb%qpts(:,iq))), ","
    5532            0 :          write(std_out,"(a,i0,a)")"  iqpt: ", iq, ","
    5533            0 :          write(std_out,"(a,i0,a)")"  iatom3: ", mu, ","
    5534            0 :          write(std_out,"(a,i0,a)")"  ispden: ", ispden, ","
    5535              :          call vd%eval(2, nfft, file_v1r(:,:,ispden,mu), intp_v1r(:,:,ispden,mu), &
    5536            0 :                       dvdb%cryst%ucvol, vd_max=vd_max, unit=std_out)
    5537            0 :          write(std_out,"(a)")"..."
    5538              :          !do ifft=1,nfft
    5539              :          !  write(std_out,*)file_v1r(1,ifft,ispden,mu),intp_v1r(1,ifft,ispden,mu),&
    5540              :          !  file_v1r(2,ifft,ispden,mu),intp_v1r(2,ifft,ispden,mu)
    5541              :          !end do
    5542              :        end do
    5543              :      end do
    5544              : 
    5545            0 :      if (ncid /= nctk_noid) then
    5546            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "coarse_v1r_abinitio"), file_v1r, start=[1,1,1,1,iq]))
    5547            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "coarse_v1r_interp"), intp_v1r, start=[1,1,1,1,iq]))
    5548              :      end if
    5549              : 
    5550            0 :      write(std_out,*)" "
    5551              :    end do ! iq
    5552              : 
    5553            0 :    write(std_out, "(/, a)")" COARSE DVDB: Max values over q-points and perturbations"
    5554            0 :    call vd_max%print()
    5555            0 :    call coarse_dvdb%free()
    5556            0 :    if (my_rank == master) call delete_file(coarse_fname, ierr)
    5557              :  end if
    5558              : 
    5559            0 :  ABI_FREE(intp_v1r)
    5560            0 :  ABI_FREE(file_v1r)
    5561              : 
    5562            0 :  if (ncid /= nctk_noid) then
    5563            0 :    NCF_CHECK(nf90_close(ncid))
    5564              :  end if
    5565              : 
    5566            0 :  call dvdb%free()
    5567            0 :  call ddb%free()
    5568              : 
    5569            0 : end subroutine dvdb_test_ftinterp
    5570              : !!***
    5571              : 
    5572              : !----------------------------------------------------------------------
    5573              : 
    5574              : !!****f* m_dvdb/dvdb_test_symcheck
    5575              : !! NAME
    5576              : !!  dvdb_test_symcheck
    5577              : !!
    5578              : !! FUNCTION
    5579              : !!  Debugging tool: checks whether Fourier-interpolating the DFPT potential independently
    5580              : !!  at q_source and at q_target = I(itimrev) S(isym) q_source (for every symmetry of the
    5581              : !!  crystal) gives results consistent with each other via the exact rotation formula
    5582              : !!  implemented in v1phq_rotate. This isolates the Fourier-interpolation machinery
    5583              : !!  (dvdb_ftinterp_qpt) from gstore_symmetrize: no e-ph coupling / m_gstore.F90 code is
    5584              : !!  involved at all. q_source need not be on the native ab-initio q-mesh.
    5585              : !!
    5586              : !! INPUTS
    5587              : !!  dvdb_filepath=Filename
    5588              : !!  dvdb_ngqpt(3)=Divisions of the Q-mesh reported in the DVDB file (usually equal to ddb_ngqpt)
    5589              : !!  dvdb_add_lr=0 to disable treatment of long-range part in Fourier interpolation.
    5590              : !!  qdamp=Defines exponential damping in LR potential
    5591              : !!  ddb_filepath=Path to DDB file. Used to treat LR part.
    5592              : !!  prtvol=Verbosity level.
    5593              : !!  qpt_source(3)=Source q-point (reduced coordinates, arbitrary, need not be on the ab-initio mesh).
    5594              : !!  comm=MPI communicator.
    5595              : !!
    5596              : !! OUTPUT
    5597              : !!  Only writing.
    5598              : !!
    5599              : !! SOURCE
    5600              : 
    5601            0 : subroutine dvdb_test_symcheck(dvdb_filepath, rspace_cell, symv1, dvdb_ngqpt, dvdb_add_lr, dvdb_qdamp, &
    5602              :                                ddb_filepath, prtvol, qpt_source, dump_path, comm)
    5603              : 
    5604              : !Arguments ------------------------------------
    5605              :  character(len=*),intent(in) :: dvdb_filepath, ddb_filepath, dump_path
    5606              :  integer,intent(in) :: comm, prtvol, dvdb_add_lr, rspace_cell, symv1
    5607              :  real(dp),intent(in) :: dvdb_qdamp
    5608              :  integer,intent(in) :: dvdb_ngqpt(3)
    5609              :  real(dp),intent(in) :: qpt_source(3)
    5610              : 
    5611              : !Local variables-------------------------------
    5612              : !scalars
    5613              :  integer,parameter :: master = 0, chneut2 = 2, qptopt1 = 1, gpu_option0 = 0, cplex2 = 2
    5614              :  integer :: nfft, isym, itimrev, tsign, mu, ispden, comm_rpt, iat, my_rank, ncid, ncerr
    5615            0 :  type(dvdb_t) :: dvdb
    5616              :  type(vdiff_t) :: vd_max, vd
    5617              : !arrays
    5618              :  integer :: ngfft(18), g0q(3)
    5619              :  real(dp) :: qpt_target(3)
    5620            0 :  real(dp),allocatable :: v1r_source(:,:,:,:), v1r_target(:,:,:,:), v1r_predicted(:,:,:,:)
    5621            0 :  type(vdiff_t),allocatable :: vd_max_atom(:)
    5622              : ! *************************************************************************
    5623              : 
    5624            0 :  my_rank = xmpi_comm_rank(comm)
    5625              : 
    5626            0 :  write(std_out,"(2a)")" Testing cross-q-point symmetry consistency of the FT interpolation of V1(r)", ch10
    5627            0 :  write(std_out,"(a)")sjoin(" q_source: ", ktoa(qpt_source))
    5628              : 
    5629            0 :  call dvdb%init(dvdb_filepath, gpu_option0, comm)
    5630            0 :  dvdb%debug = .False.
    5631            0 :  ABI_CHECK(any(symv1 == [0, 1, 2]), sjoin("invalid value of symv1:", itoa(symv1)))
    5632            0 :  dvdb%symv1 = symv1
    5633            0 :  dvdb%add_lr = dvdb_add_lr
    5634            0 :  dvdb%qdamp = dvdb_qdamp
    5635            0 :  dvdb%rspace_cell = rspace_cell
    5636              : 
    5637            0 :  if (len_trim(ddb_filepath) > 0) then
    5638            0 :    call dvdb%load_ddb(prtvol, chneut2, comm, ddb_filepath=ddb_filepath)
    5639              :  else
    5640            0 :    dvdb%add_lr = 0
    5641            0 :    ABI_WARNING("ddb_filepath was not provided --> Setting dvdb_add_lr to zero")
    5642              :  end if
    5643              : 
    5644            0 :  call dvdb%print([std_out], "", 0)
    5645              : 
    5646            0 :  call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1))
    5647            0 :  nfft = product(ngfft(1:3))
    5648            0 :  call dvdb%open_read(ngfft, comm)
    5649              : 
    5650            0 :  comm_rpt = xmpi_comm_self
    5651            0 :  call dvdb%ftinterp_setup(dvdb_ngqpt, qptopt1, 1, [zero, zero, zero], nfft, ngfft, comm_rpt)
    5652              : 
    5653            0 :  ABI_MALLOC(v1r_source, (2, nfft, dvdb%nspden, dvdb%natom3))
    5654            0 :  ABI_MALLOC(v1r_target, (2, nfft, dvdb%nspden, dvdb%natom3))
    5655            0 :  ABI_MALLOC(v1r_predicted, (2, nfft, dvdb%nspden, dvdb%natom3))
    5656            0 :  ABI_MALLOC(vd_max_atom, (dvdb%cryst%natom))
    5657              : 
    5658              :  ! Interpolate once at q_source (this itself is a genuine off-grid interpolation if q_source
    5659              :  ! is not on the coarse ab-initio mesh).
    5660            0 :  call dvdb%ftinterp_qpt(qpt_source, nfft, ngfft, v1r_source, dvdb%comm_rpt)
    5661              : 
    5662              :  ! Optionally dump v1r_target (independent re-interpolation at q_target) and v1r_predicted
    5663              :  ! (rotated prediction from q_source) to a netcdf file for post-processing in python.
    5664            0 :  ncid = nctk_noid
    5665            0 :  if (len_trim(dump_path) /= 0 .and. my_rank == master) then
    5666            0 :    write(std_out,"(a)")sjoin(" Will write target and predicted potentials to:", dump_path)
    5667            0 :    NCF_CHECK(nctk_open_create(ncid, dump_path, xmpi_comm_self))
    5668            0 :    NCF_CHECK(dvdb%cryst%ncwrite(ncid))
    5669              :    ncerr = nctk_def_dims(ncid, [ &
    5670              :      nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("nfft", nfft), nctkdim_t("nspden", dvdb%nspden), &
    5671              :      nctkdim_t("natom3", dvdb%natom3), nctkdim_t("nsym", dvdb%cryst%nsym), nctkdim_t("ntimrev", 2)], &
    5672            0 :      defmode=.True.)
    5673            0 :    NCF_CHECK(ncerr)
    5674            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("qpt_source", "dp", "three")))
    5675            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("qpt_target", "dp", "three, ntimrev, nsym")))
    5676            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1r_target", "dp", "two, nfft, nspden, natom3, ntimrev, nsym")))
    5677            0 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1r_predicted", "dp", "two, nfft, nspden, natom3, ntimrev, nsym")))
    5678            0 :    NCF_CHECK(nctk_set_datamode(ncid))
    5679            0 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpt_source"), qpt_source))
    5680              :  end if
    5681              : 
    5682            0 :  g0q = 0
    5683            0 :  do isym=1,dvdb%cryst%nsym
    5684            0 :    do itimrev=1,2
    5685            0 :      tsign = 3 - 2*itimrev
    5686            0 :      qpt_target = tsign * matmul(dvdb%cryst%symrec(:,:,isym), qpt_source)
    5687              : 
    5688              :      ! Independent, direct interpolation at the target q (no symmetry involved at all).
    5689            0 :      call dvdb%ftinterp_qpt(qpt_target, nfft, ngfft, v1r_target, dvdb%comm_rpt)
    5690              : 
    5691              :      ! Predicted potential at q_target obtained by ROTATING the q_source interpolation
    5692              :      ! with the exact same formula gstore_symmetrize/v1phq_rotate uses to expand IBZ->BZ.
    5693              :      call v1phq_rotate(dvdb%cryst, qpt_source, isym, itimrev, g0q, ngfft, cplex2, nfft, dvdb%nspden, &
    5694            0 :                         dvdb%mpi_enreg, v1r_source, v1r_predicted, xmpi_comm_self)
    5695              : 
    5696            0 :      if (ncid /= nctk_noid) then
    5697            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpt_target"), qpt_target, start=[1,itimrev,isym]))
    5698            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_target"), v1r_target, start=[1,1,1,1,itimrev,isym]))
    5699            0 :        NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_predicted"), v1r_predicted, start=[1,1,1,1,itimrev,isym]))
    5700              :      end if
    5701              : 
    5702            0 :      do mu=1,dvdb%natom3
    5703            0 :        iat = (mu - 1) / 3 + 1
    5704            0 :        do ispden=1,dvdb%nspden
    5705              :          call vd%eval(cplex2, nfft, v1r_predicted(:,:,ispden,mu), v1r_target(:,:,ispden,mu), &
    5706            0 :                       dvdb%cryst%ucvol, vd_max=vd_max)
    5707              :          call vd%eval(cplex2, nfft, v1r_predicted(:,:,ispden,mu), v1r_target(:,:,ispden,mu), &
    5708            0 :                       dvdb%cryst%ucvol, vd_max=vd_max_atom(iat))
    5709              :        end do
    5710              :      end do
    5711              : 
    5712            0 :      write(std_out,"(a)")"--- !DVDB_SYMCHECK"
    5713            0 :      write(std_out,"(a,i0,a)")"  isym: ", isym, ","
    5714            0 :      write(std_out,"(a,i0,a)")"  itimrev: ", itimrev, ","
    5715            0 :      write(std_out,"(3a)")"  qpt_target: ", trim(ktoa(qpt_target)), ","
    5716            0 :      call vd_max%print()
    5717            0 :      do iat=1,dvdb%cryst%natom
    5718            0 :        write(std_out,"(a,i0,a,es12.4)")"  atom_max_adiff[", iat, "]: ", vd_max_atom(iat)%max_adiff
    5719              :      end do
    5720            0 :      write(std_out,"(a)")"..."
    5721              :    end do ! itimrev
    5722              :  end do ! isym
    5723              : 
    5724            0 :  ABI_FREE(v1r_source)
    5725            0 :  ABI_FREE(v1r_target)
    5726            0 :  ABI_FREE(v1r_predicted)
    5727            0 :  ABI_FREE(vd_max_atom)
    5728              : 
    5729            0 :  if (ncid /= nctk_noid) then
    5730            0 :    NCF_CHECK(nf90_close(ncid))
    5731              :  end if
    5732              : 
    5733            0 :  call dvdb%free()
    5734              : 
    5735            0 : end subroutine dvdb_test_symcheck
    5736              : !!***
    5737              : 
    5738              : !----------------------------------------------------------------------
    5739              : 
    5740              : !!****f* m_dvdb/dvdb_test_symcheck_native
    5741              : !! NAME
    5742              : !!  dvdb_test_symcheck_native
    5743              : !!
    5744              : !! FUNCTION
    5745              : !!  Debugging tool: like dvdb_test_symcheck but operates on TWO LITERAL, independently
    5746              : !!  DFPT-computed q-points already present in the DVDB (no Fourier interpolation involved
    5747              : !!  at all -- no ftinterp_setup/ftinterp_qpt call anywhere). Reads q_source and q_target
    5748              : !!  directly via readsym_allv1, predicts q_target from q_source via v1phq_rotate, and
    5749              : !!  compares against q_target's own literal data. Isolates v1phq_rotate/rotate_fqg
    5750              : !!  completely from the W(R,r) real-space Fourier-interpolation machinery.
    5751              : !!
    5752              : !! INPUTS
    5753              : !!  dvdb_filepath=Filename (must contain BOTH q_source and q_target as literal,
    5754              : !!    fully-available (3*natom perturbations) q-points, e.g. produced with nsym 1).
    5755              : !!  sym_dvdb_filepath=Filename of a DIFFERENT DVDB (or any file crystal_from_file can read) that
    5756              : !!    carries the crystal's TRUE, full symmetry table (dvdb_filepath's own nsym is typically 1,
    5757              : !!    since that's what forces every requested perturbation/q to be explicitly, independently
    5758              : !!    computed in the first place -- so its own %cryst cannot be used to look up isym > 1).
    5759              : !!  qpt_source(3), qpt_target(3)=The two q-points (reduced coordinates), assumed related by
    5760              : !!    the given isym/itimrev/g0q.
    5761              : !!  isym, itimrev, g0q(3)=Symmetry indices such that qpt_target = I(itimrev) S(isym) qpt_source + g0q.
    5762              : !!  comm=MPI communicator.
    5763              : !!
    5764              : !! OUTPUT
    5765              : !!  Only writing.
    5766              : !!
    5767              : !! SOURCE
    5768              : 
    5769            0 : subroutine dvdb_test_symcheck_native(dvdb_filepath, sym_dvdb_filepath, qpt_source, qpt_target, &
    5770              :                                       isym, itimrev, g0q, comm)
    5771              : 
    5772              : !Arguments ------------------------------------
    5773              :  character(len=*),intent(in) :: dvdb_filepath, sym_dvdb_filepath
    5774              :  integer,intent(in) :: comm, isym, itimrev
    5775              :  integer,intent(in) :: g0q(3)
    5776              :  real(dp),intent(in) :: qpt_source(3), qpt_target(3)
    5777              : 
    5778              : !Local variables-------------------------------
    5779              : !scalars
    5780              :  integer,parameter :: gpu_option0 = 0, cplex2 = 2
    5781              :  integer :: nfft, mu, ispden, iq_source, iq_target, iat
    5782            0 :  type(dvdb_t) :: dvdb, sym_dvdb
    5783              :  type(vdiff_t) :: vd_max, vd
    5784              : !arrays
    5785              :  integer :: ngfft(18)
    5786            0 :  real(dp),allocatable :: v1r_source(:,:,:,:), v1r_target(:,:,:,:), v1r_predicted(:,:,:,:)
    5787            0 :  type(vdiff_t),allocatable :: vd_max_atom(:)
    5788              : ! *************************************************************************
    5789              : 
    5790            0 :  write(std_out,"(2a)")" Testing v1phq_rotate against TWO LITERAL, non-interpolated q-points", ch10
    5791            0 :  write(std_out,"(2a)")" q_source: ", trim(ktoa(qpt_source))
    5792            0 :  write(std_out,"(2a)")" q_target: ", trim(ktoa(qpt_target))
    5793              : 
    5794            0 :  call dvdb%init(dvdb_filepath, gpu_option0, comm)
    5795            0 :  dvdb%debug = .False.
    5796            0 :  call dvdb%print([std_out], "", 0)
    5797              : 
    5798            0 :  call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1))
    5799            0 :  nfft = product(ngfft(1:3))
    5800            0 :  call dvdb%open_read(ngfft, comm)
    5801              : 
    5802              :  ! Load a SEPARATE dvdb just to get the crystal's true, full symmetry table (dvdb_filepath's
    5803              :  ! own %cryst normally has nsym=1, see docstring above).
    5804            0 :  call sym_dvdb%init(sym_dvdb_filepath, gpu_option0, comm)
    5805            0 :  write(std_out,"(a,i0,a,i0)")" sym_dvdb nsym: ", sym_dvdb%cryst%nsym, "  dvdb (literal) nsym: ", dvdb%cryst%nsym
    5806              : 
    5807            0 :  iq_source = dvdb%findq(qpt_source)
    5808            0 :  iq_target = dvdb%findq(qpt_target)
    5809            0 :  ABI_CHECK(iq_source /= -1, "qpt_source not found in DVDB!")
    5810            0 :  ABI_CHECK(iq_target /= -1, "qpt_target not found in DVDB!")
    5811              : 
    5812            0 :  call dvdb%readsym_allv1(iq_source, mu, nfft, ngfft, v1r_source, comm)  ! mu reused as cplex out-arg
    5813            0 :  ABI_CHECK_IEQ(mu, cplex2, "cplex != 2 for qpt_source")
    5814            0 :  call dvdb%readsym_allv1(iq_target, mu, nfft, ngfft, v1r_target, comm)
    5815            0 :  ABI_CHECK_IEQ(mu, cplex2, "cplex != 2 for qpt_target")
    5816              : 
    5817            0 :  ABI_MALLOC(v1r_predicted, (2, nfft, dvdb%nspden, dvdb%natom3))
    5818            0 :  ABI_MALLOC(vd_max_atom, (dvdb%cryst%natom))
    5819              : 
    5820              :  call v1phq_rotate(sym_dvdb%cryst, qpt_source, isym, itimrev, g0q, ngfft, cplex2, nfft, dvdb%nspden, &
    5821            0 :                     dvdb%mpi_enreg, v1r_source, v1r_predicted, xmpi_comm_self)
    5822              : 
    5823            0 :  call sym_dvdb%free()
    5824              : 
    5825            0 :  do mu=1,dvdb%natom3
    5826            0 :    iat = (mu - 1) / 3 + 1
    5827            0 :    do ispden=1,dvdb%nspden
    5828              :      call vd%eval(cplex2, nfft, v1r_predicted(:,:,ispden,mu), v1r_target(:,:,ispden,mu), &
    5829            0 :                   dvdb%cryst%ucvol, vd_max=vd_max)
    5830              :      call vd%eval(cplex2, nfft, v1r_predicted(:,:,ispden,mu), v1r_target(:,:,ispden,mu), &
    5831            0 :                   dvdb%cryst%ucvol, vd_max=vd_max_atom(iat))
    5832              :    end do
    5833              :  end do
    5834              : 
    5835            0 :  write(std_out,"(a)")"--- !DVDB_SYMCHECK_NATIVE"
    5836            0 :  call vd_max%print()
    5837            0 :  do iat=1,dvdb%cryst%natom
    5838            0 :    write(std_out,"(a,i0,a,es12.4)")"  atom_max_adiff[", iat, "]: ", vd_max_atom(iat)%max_adiff
    5839              :  end do
    5840            0 :  write(std_out,"(a)")"..."
    5841              : 
    5842            0 :  ABI_FREE(v1r_source)
    5843            0 :  ABI_FREE(v1r_target)
    5844            0 :  ABI_FREE(v1r_predicted)
    5845            0 :  ABI_FREE(vd_max_atom)
    5846              : 
    5847            0 :  call dvdb%free()
    5848              : 
    5849            0 : end subroutine dvdb_test_symcheck_native
    5850              : !!***
    5851              : 
    5852              : !----------------------------------------------------------------------
    5853              : 
    5854              : !!****f* m_dvdb/dvdb_get_v1r_long_range
    5855              : !! NAME
    5856              : !!  dvdb_get_v1r_long_range
    5857              : !!
    5858              : !! FUNCTION
    5859              : !!  Compute the long-range part of the phonon potential
    5860              : !!  due to the Born effective charges, PRL 115, 176401 (2015) [[cite:Verdi2015]].
    5861              : !!
    5862              : !!    V^L_{iatom,idir}(r) = i (4pi/vol) sum_G (q+G) . Zeff_{iatom,idir}
    5863              : !!                           e^{i (q+G).(r - tau_{iatom})} / ((q+G) . dielt . (q+G))
    5864              : !!
    5865              : !!  where Zeff and dielt are the Born effective charge tensor and the dielectric tensor in cart coords,
    5866              : !!  tau is the atom position, and vol is the volume of the unit cell.
    5867              : !!  Note that internally the tensors are stored in Cartesian coordinates while in output we need
    5868              : !!  the contribution due to the displacement of the iatom-sublattice along the reduced direction idir
    5869              : !!  hence we need to perform some tensor gymnastics to go from Cart to reduced.
    5870              : !!
    5871              : !! INPUTS
    5872              : !!  db = the DVDB object.
    5873              : !!  qpt = the q-point in reduced coordinates.
    5874              : !!  idir = direction index.
    5875              : !!  iatom = atom index.
    5876              : !!  nfft = number of fft points.
    5877              : !!  ngfft(18) = FFT mesh.
    5878              : !!  [add_qphase]=By default, the routine returns the LR potential with the e^{iqr} phase.
    5879              : !!    Use add_qphase = 0 to get the lattice-periodic part.
    5880              : !!
    5881              : !! OUTPUT
    5882              : !!  v1r_lr = dipole potential
    5883              : !!
    5884              : !! SOURCE
    5885              : 
    5886        22234 : subroutine dvdb_get_v1r_long_range(db, qpt, idir, iatom, nfft, ngfft, v1r_lr, add_qphase)
    5887              : 
    5888              : !Arguments ------------------------------------
    5889              : !scalars
    5890              :  class(dvdb_t),intent(in) :: db
    5891              :  integer,intent(in) :: idir, iatom, nfft
    5892              :  integer,optional,intent(in) :: add_qphase
    5893              : !arrays
    5894              :  integer,intent(in) :: ngfft(18)
    5895              :  real(dp),intent(in) :: qpt(3)
    5896              :  real(dp),intent(out) :: v1r_lr(2,nfft)
    5897              : 
    5898              : !Local variables-------------------------------
    5899              : !scalars
    5900              :  integer :: n1, n2, n3, nfftot, ig, iphase, ii, jj, kk, ll, mm, ifft, ispden
    5901              :  real(dp) :: fac, qGZ, qGS, denom, denom_inv, qtau, re, im, phre, phim, qg_mod, gsq_max
    5902              :  real(dp),parameter :: tol_denom = tol8
    5903              : !arrays
    5904        22234 :  integer, allocatable :: gfft(:,:)
    5905              :  real(dp) :: gprimd(3,3), rprimd(3,3), dielt_red(3,3)
    5906              :  real(dp) :: qG_red(3), qG_cart(3), Zstar(3), Sstar(3,3), tau_red(3)
    5907        22234 :  real(dp), allocatable :: v1G_lr(:,:), v1G_lr33(:,:,:,:), workr(:,:)
    5908              : ! *************************************************************************
    5909              : 
    5910              :  ! Return immediately if metals by
    5911              :  !if (db%has_zeff .or. db%has_quadrupoles) then
    5912              : 
    5913        22234 :  iphase = 1; if (present(add_qphase)) iphase = add_qphase
    5914              : 
    5915              :  ! Make sure FFT parallelism is not used
    5916        88936 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3))
    5917        22234 :  ABI_CHECK(nfftot == nfft, "FFT parallelism not supported")
    5918              : 
    5919              :  ! Allocate memory
    5920        66702 :  ABI_MALLOC(gfft, (3, nfft))
    5921        66702 :  ABI_MALLOC(v1G_lr, (2, nfft))
    5922              : 
    5923              :  ! Reciprocal and real space primitive vectors
    5924       555850 :  gprimd = db%cryst%gprimd; rprimd = db%cryst%rprimd
    5925              : 
    5926              :  ! Prefactor
    5927        22234 :  fac = four_pi / db%cryst%ucvol
    5928              : 
    5929              :  ! Transform the Born effective charge tensor from Cartesian to reduced coordinates
    5930              :  ! and select the relevant direction.
    5931       689254 :  Zstar = matmul(transpose(gprimd), matmul(db%zeff(:,:,iatom), rprimd(:,idir))) * two_pi
    5932              : 
    5933        22234 :  if (db%has_quadrupoles) then
    5934              :    ! Transform Qstar from Cartesian to reduced coordinates and select the relevant direction.
    5935            0 :    Sstar = zero
    5936            0 :    do ii=1,3
    5937            0 :      do jj=1,3
    5938            0 :        do kk=1,3
    5939            0 :          do ll=1,3
    5940            0 :            do mm=1,3
    5941              :              Sstar(ii,jj) = Sstar(ii,jj) + &
    5942            0 :                    gprimd(mm,jj) * gprimd(ll,ii) * db%qstar(mm,ll,kk,iatom) * rprimd(kk,idir) * two_pi ** 2
    5943              :            end do
    5944              :          end do
    5945              :        end do
    5946              :      end do
    5947              :    end do
    5948              :  end if
    5949              : 
    5950              :  ! Transform the dielectric tensor from Cartesian to reduced coordinates.
    5951              :  ! q_cart e_cart q_cart = q_red (G^t e_cart G) q_red
    5952      2023294 :  dielt_red = matmul(transpose(gprimd), matmul(db%dielt, gprimd)) * two_pi ** 2
    5953              : 
    5954              :  ! Atom position
    5955        88936 :  tau_red = db%cryst%xred(:,iatom)
    5956              : 
    5957              :  ! Get the set of G vectors
    5958              :  ! TODO: May use zero-padded FFT with small G-sphere
    5959        22234 :  call get_gfft(ngfft, qpt, db%cryst%gmet, gsq_max, gfft)
    5960              : 
    5961              :  ! Compute the long-range potential in G-space due to Z* and Q* (if present)
    5962    336598582 :  v1G_lr = zero
    5963        22234 :  if (db%has_zeff .or. db%has_quadrupoles) then
    5964              : 
    5965    112214350 :    do ig=1,nfft
    5966              :      ! (q + G)
    5967    448768464 :      qG_red = qpt + gfft(:,ig)
    5968   1795073856 :      qG_cart = two_pi * matmul(db%cryst%gprimd, qG_red)
    5969    448768464 :      qG_mod = sqrt(sum(qG_cart ** 2))
    5970              :      ! (q + G) . Zeff(:,idir,iatom)
    5971    448768464 :      qGZ = dot_product(qG_red, Zstar)
    5972              :      ! (q + G) . dielt . (q + G)
    5973   1795073856 :      denom = dot_product(qG_red, matmul(dielt_red, qG_red))
    5974              :      ! Avoid (q + G) = 0
    5975    112192116 :      if (denom < tol_denom) cycle
    5976    112191608 :      denom_inv = one / denom
    5977              :      ! HM hard cutoff, in this case qdamp takes the meaning of an energy cutoff in Hartree (hardcoded to 1 for the moment)
    5978              :      !if (half*qG_mod**2 > 1) cycle
    5979    112191608 :      if (db%qdamp > zero) denom_inv = denom_inv * exp(-qG_mod ** 2 / (four * db%qdamp))
    5980    112191608 :      qGS = zero
    5981    112191608 :      if (db%has_quadrupoles) then
    5982            0 :        do ii=1,3
    5983            0 :          do jj=1,3
    5984            0 :            qGS = qGS + qG_red(ii) * qG_red(jj) * Sstar(ii,jj) / two
    5985              :          end do
    5986              :        end do
    5987              :      end if
    5988              : 
    5989              :      ! Phase factor exp(-i (q+G) . tau)
    5990    448766432 :      qtau = - two_pi * dot_product(qG_red, tau_red)
    5991    112191608 :      phre = cos(qtau); phim = sin(qtau)
    5992              :      !phre = one; phim = zero
    5993              : 
    5994    112191608 :      re = +fac * qGS * denom_inv !re = zero
    5995    112191608 :      im = fac * qGZ * denom_inv
    5996    112191608 :      v1G_lr(1,ig) = phre * re - phim * im
    5997    112213842 :      v1G_lr(2,ig) = phim * re + phre * im
    5998              :    end do
    5999              :  end if
    6000              : 
    6001              :  ! FFT to get the long-range potential in r-space
    6002        22234 :  call fourdp(2, v1G_lr, v1r_lr, 1, db%mpi_enreg, nfft, 1, ngfft, 0)
    6003              : 
    6004        22234 :  if (db%has_efield) then
    6005              :    ! Add term due to Electric field.
    6006              :    ! TODO: Change API to account for ispden/isppol. return nspden LR part
    6007              :    ! although only the electric field part depends on nsppden.
    6008              :    !v1r_lr = zero ! Comment this line to have only efield contribution
    6009            0 :    ABI_CHECK(db%nspden == 1, "nspden != 1 not coded")
    6010            0 :    ispden = 1
    6011            0 :    ABI_CALLOC(v1G_lr33, (3, 3, 2, nfft))
    6012            0 :    do ig=1,nfft
    6013              :      !if (ig > 1) cycle
    6014              :      ! (q + G)
    6015            0 :      qG_red = qpt + gfft(:,ig)
    6016            0 :      qG_cart = two_pi * matmul(db%cryst%gprimd, qG_red)
    6017            0 :      qG_mod = sqrt(sum(qG_cart ** 2))
    6018              :      ! (q + G) . Zeff(:,idir,iatom)
    6019              :      !qGZ = dot_product(qG_red, Zstar)
    6020              :      ! (q + G) . dielt . (q + G)
    6021            0 :      denom = dot_product(qG_red, matmul(dielt_red, qG_red))
    6022              :      ! Avoid (q + G) = 0
    6023            0 :      if (denom < tol_denom) cycle
    6024            0 :      denom_inv = one / denom
    6025            0 :      if (db%qdamp > zero) denom_inv = denom_inv * exp(-qG_mod ** 2 / (four * db%qdamp))
    6026            0 :      fac = (four_pi / db%cryst%ucvol) * denom_inv !* qGZ
    6027              :      ! Phase factor exp(-i (q+G) . tau)
    6028            0 :      qtau = - two_pi * dot_product(qG_red, tau_red)
    6029            0 :      phre = cos(qtau); phim = sin(qtau)
    6030              :      !phre = one; phim = zero
    6031              : 
    6032            0 :      do ii=1,3
    6033            0 :        do jj=1,3
    6034            0 :          v1G_lr33(ii, jj, 1, ig) = fac * phre * qG_red(ii) * qG_red(jj)
    6035            0 :          v1G_lr33(ii, jj, 2, ig) = fac * phim * qG_red(ii) * qG_red(jj)
    6036              :        end do
    6037              :      end do
    6038              :    end do ! ig
    6039              : 
    6040            0 :    ABI_MALLOC(workr, (2, nfft))
    6041            0 :    do ii=1,3
    6042            0 :      do jj=1,3
    6043            0 :        v1G_lr = v1G_lr33(ii, jj, :, :)
    6044            0 :        call fourdp(2, v1G_lr, workr, 1, db%mpi_enreg, nfft, 1, ngfft, 0)
    6045              :        ! Two pi comes for qpt but we should check whether the gradient wrt E-field is in gprimd or 2pi gprimd coordinates.
    6046              :        ! MG: Remove two_pi factor because jump discontinuity in the real part for G != 0 are overestimated.
    6047            0 :        do ifft=1,nfft
    6048              :          !v1r_lr(:, ifft) = v1r_lr(:, ifft) - Zstar(ii) * db%v1r_efield(ifft, jj, ispden) * workr(:, ifft) * two_pi
    6049            0 :          v1r_lr(:, ifft) = v1r_lr(:, ifft) - Zstar(ii) * db%v1r_efield(ifft, jj, ispden) * workr(:, ifft) ! * two_pi
    6050              :        end do
    6051              :      end do
    6052              :    end do
    6053              : 
    6054            0 :    ABI_FREE(workr)
    6055            0 :    ABI_FREE(v1G_lr33)
    6056              :  end if
    6057              : 
    6058              :  ! Multiply by exp(i q.r)
    6059        22234 :  if (iphase == 1) call times_eikr(qpt, ngfft, nfft, 1, v1r_lr)
    6060              : 
    6061        22234 :  ABI_FREE(gfft)
    6062        22234 :  ABI_FREE(v1G_lr)
    6063              : 
    6064        22234 : end subroutine dvdb_get_v1r_long_range
    6065              : !!***
    6066              : 
    6067              : !----------------------------------------------------------------------
    6068              : 
    6069              : !!****f* m_dvdb/dvdb_load_ddb
    6070              : !! NAME
    6071              : !!  dvdb_load_ddb
    6072              : !!
    6073              : !! FUNCTION
    6074              : !!  Load information about the Born effective charges and dielectric tensor from a DDB file
    6075              : !!
    6076              : !! TODO
    6077              : !!  Use this function in eph driver
    6078              : 
    6079            0 : subroutine dvdb_load_ddb(dvdb, chneut, prtvol, comm, ddb_filepath, ddb)
    6080              : 
    6081              : !Arguments ------------------------------------
    6082              : !scalars
    6083              :  class(dvdb_t),intent(inout) :: dvdb
    6084              :  integer,intent(in) :: chneut, prtvol, comm
    6085              :  character(len=*),optional,intent(in) :: ddb_filepath
    6086              :  type(ddb_type),optional,target,intent(in) :: ddb
    6087              : 
    6088              : !Local variables ------------------------------
    6089              :  integer,parameter :: master = 0, rfmeth1 = 1, selectz0 = 0
    6090              :  integer :: my_rank, iblock_dielt, iblock_dielt_zeff, iblock_quadrupoles
    6091              :  logical :: free_ddb
    6092            0 :  type(crystal_t) :: cryst_ddb
    6093              :  type(ddb_type),pointer :: ddb_ptr
    6094            0 :  type(ddb_type),target :: this_ddb
    6095            0 :  type(ddb_hdr_type) :: ddb_hdr
    6096              : !arrays
    6097              :  real(dp) :: dielt(3,3)
    6098            0 :  real(dp),allocatable :: zeff(:,:,:), zeff_raw(:,:,:)
    6099              : ! *************************************************************************
    6100              : 
    6101            0 :  my_rank = xmpi_comm_rank(comm)
    6102              : 
    6103            0 :  if (present(ddb_filepath)) then
    6104              :    ! Build ddb object from file. Will release memory before returning.
    6105            0 :    ABI_CHECK(.not. present(ddb), "ddb argument cannot be present when ddb_filepath is used")
    6106            0 :    call this_ddb%from_file(ddb_filepath, ddb_hdr, cryst_ddb, comm, prtvol=prtvol)
    6107            0 :    call this_ddb%set_brav(dvdb%brav)
    6108            0 :    call cryst_ddb%free()
    6109            0 :    ddb_ptr => this_ddb
    6110            0 :    free_ddb = .True.
    6111              :  else
    6112              :    ! Point input ddb, won't release memory.
    6113              :    free_ddb = .False.
    6114              :    ddb_ptr => ddb
    6115              :  end if
    6116              : 
    6117              :  ! Get dielectric Tensor
    6118            0 :  iblock_dielt = ddb_ptr%get_dielt(rfmeth1, dielt)
    6119            0 :  dvdb%dielt = dielt
    6120              : 
    6121              :  ! Get Dielectric Tensor and Effective Charges
    6122              :  ! (initialized to one_3D and zero if the derivatives are not available in the DDB file)
    6123            0 :  ABI_MALLOC(zeff, (3, 3, dvdb%natom))
    6124            0 :  ABI_MALLOC(zeff_raw, (3, 3, dvdb%natom))
    6125            0 :  iblock_dielt_zeff = ddb_ptr%get_dielt_zeff(dvdb%cryst, rfmeth1, chneut, selectz0, dielt, zeff, zeff_raw=zeff_raw)
    6126              : 
    6127            0 :  if (my_rank == master) then
    6128            0 :    if (iblock_dielt_zeff == 0) then
    6129            0 :      call wrtout(ab_out, sjoin("- Cannot find dielectric tensor and Born effective charges in DDB file:", ddb_filepath))
    6130            0 :      call wrtout(ab_out, "Values initialized with zeros")
    6131              :    else
    6132            0 :      call wrtout(ab_out, sjoin("- Found dielectric tensor and Born effective charges in DDB file:", ddb_filepath))
    6133              :    end if
    6134              :  end if
    6135              : 
    6136            0 :  if (iblock_dielt /= 0) then
    6137            0 :    dvdb%has_dielt = .True.
    6138            0 :    dvdb%dielt = dielt
    6139              :  end if
    6140            0 :  if (iblock_dielt_zeff /= 0) then
    6141            0 :    dvdb%has_zeff = .True.; dvdb%zeff = zeff; dvdb%zeff_raw = zeff_raw
    6142              :  end if
    6143            0 :  if (dvdb%has_dielt .and. (dvdb%has_zeff .or. dvdb%has_quadrupoles)) then
    6144            0 :    if (dvdb%add_lr == 0)  then
    6145              :      call wrtout([std_out, ab_out], &
    6146            0 :        " WARNING: dvdb_add_lr set to 0. Long-range term won't be subtracted in Fourier interpolation.")
    6147              :    end if
    6148              :  end if
    6149              : 
    6150              :  ! Read the quadrupoles
    6151            0 :  iblock_quadrupoles = ddb_ptr%get_quadrupoles(ddb_hdr%ddb_version,1,BLKTYP_d3E_xx,dvdb%qstar)
    6152            0 :  if (iblock_quadrupoles /=0) dvdb%has_quadrupoles = .True.
    6153              : 
    6154            0 :  if (present(ddb_filepath)) call ddb_hdr%free()
    6155              : 
    6156            0 :  ABI_FREE(zeff)
    6157            0 :  ABI_FREE(zeff_raw)
    6158            0 :  if (free_ddb) call ddb_ptr%free()
    6159              : 
    6160            0 : end subroutine dvdb_load_ddb
    6161              : !!***
    6162              : 
    6163              : !!****f* m_dvdb/dvdb_load_efield
    6164              : !! NAME
    6165              : !!  dvdb_load_efield
    6166              : !!
    6167              : !! FUNCTION
    6168              : !!  Load first order derivatives wrt the electric file from files
    6169              : !!
    6170              : !! INPUTS
    6171              : !!  pot_paths=List of strings with paths to POT1 files.
    6172              : !!  comm=MPI communicator.
    6173              : 
    6174            0 : subroutine dvdb_load_efield(dvdb, pot_paths, comm)
    6175              : 
    6176              : !Arguments ------------------------------------
    6177              : !scalars
    6178              :  class(dvdb_t),intent(inout) :: dvdb
    6179              :  integer,intent(in) :: comm
    6180              :  character(len=*),intent(in) :: pot_paths(3)
    6181              : 
    6182              : !Local variables-------------------------------
    6183              : !scalars
    6184              :  integer,parameter :: pawread0 = 0, cplex1 = 1
    6185              :  integer :: ii, idir, ipert, nfft
    6186            0 :  type(hdr_type) :: hdr
    6187              : !arrays
    6188            0 :  real(dp),allocatable :: v1e_red(:,:,:)
    6189            0 :  type(pawrhoij_type),allocatable :: pawrhoij(:)
    6190              : ! *************************************************************************
    6191              : 
    6192            0 :  ABI_CHECK(all(dvdb%ngfft /= -1), "dbvd%ngfft must be defined!")
    6193              : 
    6194            0 :  nfft = product(dvdb%ngfft(1:3))
    6195            0 :  ABI_CALLOC(v1e_red, (nfft, dvdb%nspden, 3))
    6196              : 
    6197            0 :  do ii=1,3
    6198              :    ! Read DFPT potentials due to E-field.
    6199              :    ! TODO: Should implement symmetries so that only the irred pots are needed.
    6200            0 :    call wrtout(std_out, sjoin("Loading Efield DFPT potential from:", pot_paths(ii)))
    6201              :    call read_rhor(pot_paths(ii), cplex1, dvdb%nspden, nfft, dvdb%ngfft, pawread0, &
    6202            0 :      dvdb%mpi_enreg, v1e_red(:,:,ii), hdr, pawrhoij, comm, allow_interp=.True., want_varname="first_order_potential")
    6203              : 
    6204              :    ! Consistency check: expecting E-field perturbation.
    6205            0 :    idir = mod(hdr%pertcase - 1, 3) + 1; ipert = (hdr%pertcase - idir) / 3 + 1
    6206            0 :    ABI_CHECK(all(abs(hdr%qptn) < tol12), sjoin("Expecting Gamma point in E-field pert, got qpt:", ktoa(hdr%qptn)))
    6207            0 :    ABI_CHECK(ipert == hdr%natom + 2, sjoin("Expecting E-field perturbation, got ipert:", itoa(ipert)))
    6208            0 :    ABI_CHECK(idir == ii, sjoin("Expecting E-field perturbation along idir:", itoa(ii), " got idir:", itoa(idir)))
    6209            0 :    call hdr%free()
    6210              :  end do
    6211              : 
    6212              :  ! Transfer data.
    6213            0 :  ABI_MALLOC(dvdb%v1r_efield, (nfft, 3, dvdb%nspden))
    6214            0 :  do ii=1,3
    6215            0 :    dvdb%v1r_efield(:,ii,:) = v1e_red(:,:,ii)
    6216              :  end do
    6217            0 :  ABI_FREE(v1e_red)
    6218              : 
    6219            0 :  dvdb%has_efield = .True.
    6220              : 
    6221            0 : end subroutine dvdb_load_efield
    6222              : !!***
    6223              : 
    6224              : !----------------------------------------------------------------------
    6225              : 
    6226              : !!****f* m_dvdb/dvdb_interpolate_and_write
    6227              : !! NAME
    6228              : !!  dvdb_interpolate_and_write
    6229              : !!
    6230              : !! FUNCTION
    6231              : !!  Interpolate the phonon potential onto a fine q-point grid
    6232              : !!  and write the data in a new DVDB file.
    6233              : !!
    6234              : !! INPUTS
    6235              : !!
    6236              : !! OUTPUT
    6237              : !!
    6238              : !! SOURCE
    6239              : 
    6240            8 : subroutine dvdb_interpolate_and_write(dvdb, dtset, new_dvdb_fname, ngfft, ngfftf, cryst, &
    6241            8 :            ngqpt_coarse, nqshift_coarse, qshift_coarse, comm, custom_qpt)
    6242              : 
    6243              : !Arguments ------------------------------------
    6244              : !scalars
    6245              :  integer,intent(in) :: nqshift_coarse, comm
    6246              :  character(len=*),intent(in) :: new_dvdb_fname
    6247              :  type(crystal_t),intent(in) :: cryst
    6248              :  class(dvdb_t),intent(inout) :: dvdb
    6249              :  type(dataset_type),intent(in) :: dtset
    6250              : !arrays
    6251              :  integer,intent(in) :: ngfft(18), ngfftf(18)
    6252              :  integer,intent(in) :: ngqpt_coarse(3)
    6253              :  real(dp),intent(in) :: qshift_coarse(3,nqshift_coarse)
    6254              :  real(dp),optional,intent(in) :: custom_qpt(:,:)
    6255              : 
    6256              : !Local variables ------------------------------
    6257              : !scalars
    6258              :  integer,parameter :: master=0, fform_pot=111
    6259              :  integer :: my_rank,nproc,idir,ipert,iat,ipc,ispden, ierr
    6260              :  integer :: cplex,db_iqpt,natom,natom3,npc,trev_q,nspden
    6261              :  integer :: nqbz, nqibz, iq, ifft, nqbz_coarse
    6262              :  integer :: nperts_read, nperts_interpolate, nperts
    6263              :  integer :: nqpt_read, nqpt_interpolate, qptopt
    6264              :  integer :: nfft,nfftf, dimv1, ount, unt, fform, ncid, ncerr
    6265              :  logical :: use_netcdf
    6266              :  real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all
    6267              :  character(len=500) :: msg
    6268              :  character(len=fnlen) :: tmp_fname
    6269            8 :  type(hdr_type) :: hdr_ref
    6270              : !arrays
    6271           16 :  integer :: qptrlatt(3,3), rfdir(3), symq(4,2,cryst%nsym)
    6272            8 :  integer,allocatable :: pinfo(:,:),rfpert(:),pertsy(:,:,:),iq_read(:),this_pertsy(:,:)
    6273              :  real(dp) :: qpt(3), rhog1_g0(2)
    6274            8 :  real(dp),allocatable :: v1scf(:,:,:), v1scf_rpt(:,:,:,:),v1(:)
    6275            8 :  real(dp),allocatable :: wtq(:),qibz(:,:),qbz(:,:),q_interp(:,:),q_read(:,:)
    6276              : !************************************************************************
    6277              : 
    6278            8 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
    6279              : 
    6280            8 :  write(msg, '(2a)') " Interpolation of the electron-phonon coupling potential", ch10
    6281            8 :  call wrtout(ab_out, msg, do_flush=.True.); call wrtout(std_out, msg, do_flush=.True.)
    6282              : 
    6283            8 :  call cwtime(cpu_all, wall_all, gflops_all, "start")
    6284              : 
    6285            8 :  if (dtset%eph_task == 5 .or. present(custom_qpt)) then
    6286            7 :    msg = sjoin(" From coarse q-mesh:", ltoa(ngqpt_coarse), "to:", ltoa(dtset%eph_ngqpt_fine))
    6287           21 :    call wrtout([std_out, ab_out], msg)
    6288              :    ! Setup fine q-point grid in the IBZ
    6289              :    ! Generate the list of irreducible q-points in the grid
    6290            7 :    qptrlatt = 0
    6291            7 :    qptrlatt(1,1) = dtset%eph_ngqpt_fine(1); qptrlatt(2,2) = dtset%eph_ngqpt_fine(2); qptrlatt(3,3) = dtset%eph_ngqpt_fine(3)
    6292            7 :    qptopt = 1; if (dtset%qptopt /= 0) qptopt = dtset%qptopt
    6293            7 :    call wrtout(std_out, sjoin(" Generating q-IBZ for DVDB with qptopt:", itoa(qptopt)))
    6294            7 :    call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, 1, [zero, zero, zero], nqibz, qibz, wtq, nqbz, qbz)
    6295              : 
    6296            1 :  else if (dtset%eph_task == -5) then
    6297            1 :    msg = sjoin(" Using list of q-points specified by ph_qpath with ", itoa(dtset%ph_nqpath), "qpoints")
    6298            3 :    call wrtout([std_out, ab_out], msg)
    6299            1 :    ABI_CHECK(dtset%ph_nqpath > 0, "ph_nqpath must be specified when eph_task == -5")
    6300            1 :    nqibz = dtset%ph_nqpath
    6301            3 :    ABI_MALLOC(qibz, (3, nqibz))
    6302           22 :    qibz = dtset%ph_qpath(:, 1:nqibz)
    6303            8 :    ABI_CALLOC(wtq, (nqibz))
    6304            1 :    nqbz = nqibz
    6305            2 :    ABI_MALLOC(qbz, (3, nqbz))
    6306           22 :    qbz = qibz
    6307              : 
    6308              :  else
    6309            0 :    ABI_ERROR(sjoin("Invalid eph_task", itoa(dtset%eph_task)))
    6310              :  end if
    6311              : 
    6312            8 :  if (present(custom_qpt)) then
    6313            0 :   ABI_SFREE(qibz)
    6314            0 :   ABI_SFREE(wtq)
    6315            0 :   ABI_SFREE(qbz)
    6316            0 :   nqibz = size(custom_qpt,dim=2)
    6317            0 :   ABI_MALLOC(qibz, (3, nqibz))
    6318            0 :   qibz = custom_qpt
    6319            0 :   ABI_CALLOC(wtq, (nqibz))
    6320            0 :   nqbz = nqibz
    6321            0 :   ABI_MALLOC(qbz, (3, nqbz))
    6322            0 :   qbz = qibz
    6323              :  end if
    6324              : 
    6325           32 :  nfft = product(ngfft(1:3)); nfftf = product(ngfftf(1:3))
    6326              : 
    6327              :  ! check that ngqpt_coarse is in DVDB.
    6328           32 :  nqbz_coarse = product(ngqpt_coarse) * nqshift_coarse
    6329              : 
    6330              :  ! ==========================================
    6331              :  ! Prepare the header to write the potentials
    6332              :  ! ==========================================
    6333              : 
    6334              :  ! Read the first header
    6335            8 :  if (my_rank == master) then
    6336            8 :    if (open_file(dvdb%path, msg, newunit=unt, form="unformatted", status="old", action="read") /= 0) then
    6337            0 :      ABI_ERROR(msg)
    6338              :    end if
    6339            8 :    read(unt, err=10, iomsg=msg) dvdb%version
    6340            8 :    read(unt, err=10, iomsg=msg) dvdb%numv1
    6341              : 
    6342            8 :    call hdr_ref%fort_read(unt, fform)
    6343            8 :    if (dvdb_check_fform(fform, "read_dvdb", msg) /= 0) then
    6344            0 :      ABI_ERROR(sjoin("While reading:", dvdb%path, ch10, msg))
    6345              :    end if
    6346            8 :    close(unt)
    6347              :  end if
    6348              : 
    6349              :  ! Reset the symmetries of the header
    6350              :  ! One might have disable the symmetries in the response function calculation
    6351              :  ! that produced the initial set of potentials present in the DVDB.
    6352              :  ! This is because the symmetry features are not used in all parts
    6353              :  ! of the response function driver.
    6354              :  !write(std_out,*)hdr_ref%nsym, cryst%nsym
    6355              :  !ABI_CHECK(hdr_ref%nsym == cryst%nsym, "Diff nsym")
    6356            8 :  ABI_SFREE(hdr_ref%symrel)
    6357            8 :  ABI_SFREE(hdr_ref%tnons)
    6358            8 :  ABI_SFREE(hdr_ref%symafm)
    6359            8 :  hdr_ref%nsym = cryst%nsym
    6360           24 :  ABI_MALLOC(hdr_ref%symrel, (3,3,hdr_ref%nsym))
    6361           24 :  ABI_MALLOC(hdr_ref%tnons, (3,hdr_ref%nsym))
    6362           24 :  ABI_MALLOC(hdr_ref%symafm, (hdr_ref%nsym))
    6363              : 
    6364         5000 :  hdr_ref%symrel(:,:,:) = cryst%symrel(:,:,:)
    6365         1544 :  hdr_ref%tnons(:,:) = cryst%tnons(:,:)
    6366          392 :  hdr_ref%symafm(:) = cryst%symafm(:)
    6367           32 :  hdr_ref%ngfft = ngfftf(1:3)
    6368              : 
    6369              :  ! =======================================
    6370              :  ! Open DVDB and copy important dimensions
    6371              :  ! =======================================
    6372              : 
    6373            8 :  call dvdb%open_read(ngfftf, xmpi_comm_self)
    6374              : 
    6375              :  ! Besides perturbations with same q-points won't be contiguous on file --> IO is gonna be inefficient.
    6376           16 :  call dvdb%print([std_out], "", dtset%prtvol)
    6377              : 
    6378            8 :  natom = cryst%natom
    6379            8 :  natom3 = 3 * natom
    6380            8 :  nspden = dvdb%nspden
    6381              : 
    6382              :  ! ==================================================
    6383              :  ! Sort the q-points to read and those to interpolate
    6384              :  ! and find the irreducible perturbations
    6385              :  ! ==================================================
    6386           24 :  ABI_MALLOC(iq_read, (nqibz))
    6387           24 :  ABI_MALLOC(q_read, (3,nqibz))
    6388           16 :  ABI_MALLOC(q_interp, (3,nqibz))
    6389           32 :  ABI_MALLOC(pertsy, (nqibz,3,dvdb%mpert))
    6390           24 :  ABI_MALLOC(this_pertsy, (3,dvdb%mpert))
    6391           24 :  ABI_MALLOC(rfpert, (dvdb%mpert))
    6392           24 :  ABI_MALLOC(pinfo, (3,3*dvdb%mpert))
    6393          110 :  rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1
    6394              : 
    6395         2645 :  pertsy = 0
    6396            8 :  nqpt_read = 0
    6397            8 :  nperts_read = 0
    6398            8 :  nqpt_interpolate = 0
    6399            8 :  nperts_interpolate = 0
    6400              : 
    6401          111 :  do iq=1,nqibz
    6402          412 :    qpt = qibz(:,iq)
    6403              : 
    6404              :    ! Find the index of the q-point in the DVDB.
    6405          103 :    db_iqpt = dvdb%findq(qpt)
    6406              :    !if (db_iqpt /= 1) db_iqpt = -1
    6407              : 
    6408          111 :    if (db_iqpt /= -1) then
    6409           29 :      if (dvdb%prtvol > 0) call wrtout(std_out, sjoin("Q-point: ",ktoa(qpt)," found in DVDB with index ",itoa(db_iqpt)))
    6410           29 :      nqpt_read = nqpt_read + 1
    6411          116 :      q_read(:,nqpt_read) = qpt(:)
    6412           29 :      iq_read(nqpt_read) = db_iqpt
    6413              : 
    6414              :      ! Count the perturbations
    6415           29 :      npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo)
    6416           85 :      do ipc=1,npc
    6417           56 :        idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc)
    6418           85 :        if (iat .le. natom) nperts_read = nperts_read + 1
    6419              :      end do
    6420              : 
    6421              :    else
    6422           74 :      if (dvdb%prtvol > 0) call wrtout(std_out, sjoin("Q-point: ",ktoa(qpt), "not found in DVDB. Will interpolate."))
    6423           74 :      nqpt_interpolate = nqpt_interpolate + 1
    6424          296 :      q_interp(:,nqpt_interpolate) = qpt(:)
    6425              : 
    6426              :      ! Examine the symmetries of the q wavevector
    6427           74 :      call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,trev_q,prtvol=0)
    6428              : 
    6429              :      ! Find the list of irreducible perturbations for this q-point.
    6430              :      call irreducible_set_pert(cryst%indsym,dvdb%mpert,cryst%natom,cryst%nsym,&
    6431           74 :          this_pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel)
    6432         2358 :          pertsy(nqpt_interpolate,:,:) = this_pertsy
    6433              :      !pertsy = 1
    6434              : 
    6435          201 :      do iat=1,natom
    6436          582 :        do idir=1,3
    6437          381 :          ipert = (iat-1) * 3 + idir
    6438          508 :          if (pertsy(nqpt_interpolate,idir,iat) == 1) nperts_interpolate = nperts_interpolate + 1
    6439              :        end do
    6440              :      end do
    6441              : 
    6442              :    end if
    6443              :  end do
    6444              : 
    6445           24 :  call wrtout([std_out, ab_out], sjoin(" Number of q-points found in input DVDB:", itoa(nqpt_read)))
    6446           24 :  call wrtout([std_out, ab_out], sjoin(" Number of q-points requiring Fourier interpolation", itoa(nqpt_interpolate)))
    6447              : 
    6448              :  ! =================================================
    6449              :  ! Open the new DVDB file and write preliminary info
    6450              :  ! =================================================
    6451            8 :  nperts = nperts_read + nperts_interpolate
    6452              : 
    6453            8 :  if (my_rank == master) then
    6454            8 :    if (open_file(new_dvdb_fname, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then
    6455            0 :      ABI_ERROR(msg)
    6456              :    end if
    6457            8 :    write(ount, err=10, iomsg=msg) dvdb_last_version
    6458            8 :    write(ount, err=10, iomsg=msg) nperts
    6459              :  end if
    6460              : 
    6461              :  ! =================================================================
    6462              :  ! Master reads all available perturbations and copy in the new DVDB
    6463              :  ! =================================================================
    6464              : 
    6465            0 :  rhog1_g0 = zero
    6466              : 
    6467              :  if (my_rank == master) then
    6468           37 :    do iq=1,nqpt_read
    6469          116 :      qpt = q_read(:,iq)
    6470           29 :      db_iqpt = iq_read(iq)
    6471              : 
    6472              :      ! Read each irreducible perturbation potentials
    6473           29 :      npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo)
    6474           29 :      ABI_CHECK(npc /= 0, "npc == 0!")
    6475              : 
    6476              :      ! These arrays depend on cplex.
    6477          145 :      ABI_MALLOC(v1scf, (cplex, nfftf, nspden))
    6478           87 :      ABI_MALLOC(v1, (cplex*nfftf))
    6479              : 
    6480           85 :      do ipc=1,npc
    6481           56 :        idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc)
    6482           56 :        if (dvdb%read_onev1(idir, iat, db_iqpt, cplex, nfftf, ngfftf, v1scf, msg) /= 0) then
    6483            0 :          ABI_ERROR(msg)
    6484              :        end if
    6485              : 
    6486              :        ! Write header
    6487          224 :        hdr_ref%qptn = qpt
    6488           56 :        hdr_ref%pertcase = ipert
    6489           56 :        call hdr_ref%fort_write(ount, fform_pot, ierr)
    6490           56 :        ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0")
    6491              : 
    6492          112 :        do ispden=1,nspden
    6493          112 :          v1 = reshape(v1scf(:,:,ispden), (/cplex*nfftf/))
    6494          112 :          write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf)
    6495              :        end do
    6496           85 :        if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    6497              :      end do
    6498              : 
    6499           29 :      ABI_FREE(v1scf)
    6500           37 :      ABI_FREE(v1)
    6501              :    end do
    6502              :  end if ! master
    6503              : 
    6504            8 :  call xmpi_barrier(comm)
    6505              : 
    6506              :  ! ================================================================
    6507              :  ! Interpolate the potential for q-points not in the original DVDB
    6508              :  ! ================================================================
    6509              : 
    6510            8 :  dvdb%my_nrpt = nqbz_coarse
    6511           40 :  ABI_MALLOC_OR_DIE(v1scf_rpt, (2, dvdb%my_nrpt, nfftf, dvdb%nspden), ierr)
    6512              : 
    6513            8 :  cplex = 2
    6514           32 :  ABI_MALLOC(v1scf, (cplex,nfftf,nspden))
    6515           24 :  ABI_MALLOC(v1, (cplex*nfftf))
    6516              : 
    6517              :  use_netcdf = .False.
    6518              :  ! Create temporary netcdf file used to write Fortran file with contiguous perturbations.
    6519            8 :  use_netcdf = .True.
    6520            8 :  if (my_rank == master) then
    6521            8 :    tmp_fname = strcat(new_dvdb_fname, "_TEMPORARY_TRANSFER_FILE.nc")
    6522            8 :    dimv1 = cplex * nfftf
    6523            8 :    NCF_CHECK(nctk_open_create(ncid, tmp_fname, xmpi_comm_self))
    6524              :    ncerr = nctk_def_dims(ncid, [&
    6525              :      nctkdim_t("dimv1", dimv1), nctkdim_t("nspden", nspden), &
    6526              :      nctkdim_t("natom", natom), nctkdim_t("nqpt_intp", nqpt_interpolate), &
    6527              :      nctkdim_t("nrpt", dvdb%my_nrpt), nctkdim_t("nfft", nfftf), nctkdim_t("natom3", natom * 3) &
    6528           64 :    ])
    6529            8 :    NCF_CHECK(ncerr)
    6530            8 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1", "dp", "dimv1, nspden, three, natom, nqpt_intp")))
    6531              :    !NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1scf_rpt", "dp", "two, nrpt, nfft, nspden, natom3")))
    6532            8 :    NCF_CHECK(nctk_set_datamode(ncid))
    6533              :  end if
    6534              : 
    6535           23 :  do iat=1,natom
    6536           68 :    do idir=1,3
    6537           45 :      ipert = (iat-1) * 3 + idir
    6538              : 
    6539              :      ! Entry set to -1 for perturbations that can be found from basis perturbations.
    6540          576 :      if (sum(pertsy(:,idir,iat)) == -nqpt_interpolate) cycle
    6541              : 
    6542           31 :      call wrtout(std_out, sjoin(" Interpolating perturbation iat, idir = ",itoa(iat), itoa(idir)), do_flush=.True.)
    6543           31 :      call cwtime(cpu, wall, gflops, "start")
    6544              : 
    6545              :      ! TODO: This part is slow.
    6546              :      ! Compute phonon potential in real space lattice representation.
    6547              :      call dvdb_get_v1scf_rpt(dvdb, cryst, ngqpt_coarse, nqshift_coarse, &
    6548              :                              qshift_coarse, nfftf, ngfftf, &
    6549           31 :                              dvdb%my_nrpt, dvdb%nspden, ipert, v1scf_rpt, comm)
    6550              : 
    6551              :      !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1scf_rpt"), v1scf_rpt, start=[1,1,1,1,ipert]))
    6552           31 :      call cwtime_report(" v1scf_rpt built", cpu, wall, gflops)
    6553              : 
    6554          348 :      do iq=1,nqpt_interpolate
    6555          317 :        if (pertsy(iq,idir,iat) == -1) cycle
    6556          976 :        qpt = q_interp(:,iq)
    6557              : 
    6558              :        ! Interpolate the phonon potential
    6559              :        call dvdb_get_v1scf_qpt(dvdb, cryst, qpt, nfftf, ngfftf, dvdb%my_nrpt, &
    6560          244 :                                dvdb%nspden, ipert, v1scf_rpt, v1scf, comm)
    6561              : 
    6562              :        !call wrtout(std_out, sjoin("Writing q-point", itoa(iq)))
    6563          275 :        if (my_rank == master) then
    6564              :          if (use_netcdf) then
    6565              :            ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1"), v1scf, &
    6566         2684 :                start=[1,1,idir,iat,iq], count=[dimv1,nspden,1,1,1])
    6567          244 :            NCF_CHECK(ncerr)
    6568              :          else
    6569              :            ! Master writes the file (change also qpt and ipert in hdr%)
    6570              :            hdr_ref%qptn = qpt
    6571              :            hdr_ref%pertcase = ipert
    6572              :            call hdr_ref%fort_write(ount, fform_pot, ierr)
    6573              :            ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0")
    6574              : 
    6575              :            do ispden=1,nspden
    6576              :              v1 = reshape(v1scf(:,:,ispden), [cplex*nfftf])
    6577              :              write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf)
    6578              :            end do
    6579              :            if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    6580              :          end if
    6581              :        end if
    6582              :      end do
    6583              : 
    6584           31 :      call cwtime_report(" q-points interpolated and written to new DVDB file.", cpu, wall, gflops)
    6585          122 :      ABI_FREE(dvdb%my_rpt)
    6586              :    end do
    6587              :  end do
    6588              : 
    6589            8 :  if (use_netcdf .and. my_rank == master) then
    6590           82 :    do iq=1,nqpt_interpolate
    6591          296 :      qpt = q_interp(:,iq)
    6592          209 :      do iat=1,natom
    6593          582 :        do idir=1,3
    6594          381 :          if (pertsy(iq,idir,iat) == -1) cycle
    6595          244 :          ipert = (iat-1) * 3 + idir
    6596          976 :          hdr_ref%qptn = qpt
    6597          244 :          hdr_ref%pertcase = ipert
    6598          244 :          call hdr_ref%fort_write(ount, fform_pot, ierr)
    6599              :          ncerr = nf90_get_var(ncid, nctk_idname(ncid, "v1"), v1scf, &
    6600         2684 :              start=[1,1,idir,iat,iq], count=[dimv1,nspden,1,1,1])
    6601          244 :          NCF_CHECK(ncerr)
    6602          488 :          do ispden=1,nspden
    6603          488 :            v1 = reshape(v1scf(:,:,ispden), [cplex*nfftf])
    6604          488 :            write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf)
    6605              :          end do
    6606          371 :          if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    6607              :        end do
    6608              :     end do
    6609              :    end do
    6610            8 :    NCF_CHECK(nf90_close(ncid))
    6611            8 :    call delete_file(tmp_fname, ierr)
    6612              :  end if
    6613              : 
    6614            8 :  if (my_rank == master) close(ount)
    6615              : 
    6616              :  ! Free memory
    6617            8 :  ABI_FREE(v1scf)
    6618            8 :  ABI_FREE(v1)
    6619            8 :  ABI_FREE(v1scf_rpt)
    6620            8 :  ABI_FREE(qbz)
    6621            8 :  ABI_FREE(qibz)
    6622            8 :  ABI_FREE(q_interp)
    6623            8 :  ABI_FREE(q_read)
    6624            8 :  ABI_FREE(wtq)
    6625            8 :  ABI_FREE(iq_read)
    6626            8 :  ABI_FREE(pertsy)
    6627            8 :  ABI_FREE(this_pertsy)
    6628            8 :  ABI_FREE(rfpert)
    6629            8 :  ABI_FREE(pinfo)
    6630              : 
    6631            8 :  call hdr_ref%free()
    6632              : 
    6633            8 :  write(msg, '(2a)') "Interpolation of the electron-phonon coupling potential completed", ch10
    6634           24 :  call wrtout([std_out, ab_out], msg, do_flush=.True.)
    6635              : 
    6636            8 :  call cwtime_report(" Overall time:", cpu_all, wall_all, gflops_all)
    6637              : 
    6638            8 :  return
    6639              : 
    6640              :  ! Handle Fortran IO error
    6641              : 10 continue
    6642            0 :  ABI_ERROR(msg)
    6643              : 
    6644           24 : end subroutine dvdb_interpolate_and_write
    6645              : !!***
    6646              : 
    6647              : !----------------------------------------------------------------------
    6648              : 
    6649              : !!****f* m_dvdb/dvdb_qdownsample
    6650              : !! NAME
    6651              : !!  dvdb_qdownsample
    6652              : !!
    6653              : !! FUNCTION
    6654              : !!  Downsample the q-mesh. Produce new DVDB file
    6655              : !!
    6656              : !! INPUTS
    6657              : !!  new_dvdb_fname=Path of output DVDB
    6658              : !!  qptopt=option for the generation of q points (defines whether spatial symmetries and/or time-reversal can be used)
    6659              : !!  ngqpt(3)=Division of coarse Q-mesh
    6660              : !!  comm=MPI communicator.
    6661              : !!
    6662              : !! OUTPUT
    6663              : !!  Only writing
    6664              : !!
    6665              : !! SOURCE
    6666              : 
    6667            0 : subroutine dvdb_qdownsample(dvdb, new_dvdb_fname, qptopt, ngqpt, comm)
    6668              : 
    6669              : !Arguments ------------------------------------
    6670              : !scalars
    6671              :  integer,intent(in) :: comm
    6672              :  class(dvdb_t),intent(inout) :: dvdb
    6673              :  character(len=*),intent(in) :: new_dvdb_fname
    6674              : !arrays
    6675              :  integer,intent(in) :: qptopt, ngqpt(3)
    6676              : 
    6677              : !Local variables ------------------------------
    6678              : !scalars
    6679              :  integer,parameter :: master=0, fform_pot=111
    6680              :  integer :: ierr,my_rank,nproc,idir,ipert,iat,ipc,ispden
    6681              :  integer :: cplex, db_iqpt, npc, nqbz, nqibz, iq, ifft, nperts_read, nfft, ount
    6682              :  character(len=500) :: msg
    6683              : !arrays
    6684              :  integer :: qptrlatt(3,3)
    6685            0 :  integer,allocatable :: iq_read(:), pinfo(:,:)
    6686              :  real(dp) :: rhog1_g0(2)
    6687            0 :  real(dp),allocatable :: v1scf(:,:,:), v1(:), wtq(:), qibz(:,:), qbz(:,:)
    6688              : !************************************************************************
    6689              : 
    6690            0 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
    6691            0 :  if (my_rank /= master) goto 20
    6692              : 
    6693            0 :  nfft = product(dvdb%ngfft(1:3))
    6694              : 
    6695              :  ! =======================
    6696              :  ! Setup fine q-point grid
    6697              :  ! =======================
    6698              :  ! Generate the list of irreducible q-points in the coarse grid
    6699            0 :  qptrlatt = 0; qptrlatt(1,1) = ngqpt(1); qptrlatt(2,2) = ngqpt(2); qptrlatt(3,3) = ngqpt(3)
    6700            0 :  call kpts_ibz_from_kptrlatt(dvdb%cryst, qptrlatt, qptopt, 1, [zero, zero, zero], nqibz, qibz, wtq, nqbz, qbz)
    6701              : 
    6702              :  ! =======================================
    6703              :  ! Open DVDB and copy important dimensions
    6704              :  ! =======================================
    6705              : 
    6706            0 :  ABI_MALLOC(iq_read, (nqibz))
    6707            0 :  ABI_MALLOC(pinfo, (3, 3*dvdb%mpert))
    6708            0 :  nperts_read = 0
    6709              : 
    6710            0 :  do iq=1,nqibz
    6711              :    ! Find the index of the q-point in the DVDB.
    6712            0 :    db_iqpt = dvdb%findq(qibz(:, iq))
    6713            0 :    ABI_CHECK(db_iqpt /= -1, sjoin("Q-point:", ktoa(qibz(:, iq)), "not found in DVDB!"))
    6714            0 :    iq_read(iq) = db_iqpt
    6715              : 
    6716              :    ! Count the number of perturbations.
    6717            0 :    npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo)
    6718            0 :    do ipc=1,npc
    6719            0 :      idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc)
    6720            0 :      if (iat <= dvdb%cryst%natom) nperts_read = nperts_read + 1
    6721              :    end do
    6722              :  end do
    6723              : 
    6724              :  ! =================================================
    6725              :  ! Open the new DVDB file and write preliminary info
    6726              :  ! =================================================
    6727              :  !nperts = nperts_read + nperts_interpolate
    6728            0 :  if (open_file(new_dvdb_fname, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then
    6729            0 :    ABI_ERROR(msg)
    6730              :  end if
    6731            0 :  write(ount, err=10, iomsg=msg) dvdb_last_version
    6732            0 :  write(ount, err=10, iomsg=msg) nperts_read
    6733              : 
    6734              :  ! Read all perturbations on the coarse Q-mesh and write them to the new DVDB
    6735            0 :  rhog1_g0 = zero
    6736              : 
    6737            0 :  do iq=1,nqibz
    6738            0 :    db_iqpt = iq_read(iq)
    6739              : 
    6740              :    ! Read each irreducible perturbation potentials
    6741            0 :    npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo)
    6742            0 :    ABI_CHECK(npc /= 0, "npc == 0!")
    6743              : 
    6744            0 :    ABI_MALLOC(v1scf, (cplex, nfft, dvdb%nspden))
    6745            0 :    ABI_MALLOC(v1, (cplex*nfft))
    6746              : 
    6747            0 :    do ipc=1,npc
    6748            0 :      idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc)
    6749            0 :      if (dvdb%read_onev1(idir, iat, db_iqpt, cplex, nfft, dvdb%ngfft, v1scf, msg) /= 0) then
    6750            0 :        ABI_ERROR(msg)
    6751              :      end if
    6752              : 
    6753              :      ! Change the header.
    6754            0 :      dvdb%hdr_ref%qptn = qibz(:, iq)
    6755            0 :      dvdb%hdr_ref%pertcase = ipert
    6756              : 
    6757              :      ! Write header
    6758            0 :      call dvdb%hdr_ref%fort_write(ount, fform_pot, ierr)
    6759            0 :      ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0")
    6760              : 
    6761            0 :      do ispden=1,dvdb%nspden
    6762            0 :        v1 = reshape(v1scf(:,:,ispden), [cplex*nfft])
    6763            0 :        write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft)
    6764              :      end do
    6765            0 :      if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0
    6766              :    end do
    6767              : 
    6768            0 :    ABI_FREE(v1scf)
    6769            0 :    ABI_FREE(v1)
    6770              :  end do
    6771              : 
    6772            0 :  close(ount)
    6773              : 
    6774              :  ! Free memory
    6775            0 :  ABI_FREE(qbz)
    6776            0 :  ABI_FREE(qibz)
    6777            0 :  ABI_FREE(wtq)
    6778            0 :  ABI_FREE(iq_read)
    6779            0 :  ABI_FREE(pinfo)
    6780              : 
    6781            0 :  write(msg, '(2a)') " Downsampling of the e-ph coupling potential completed", ch10
    6782            0 :  call wrtout(std_out, msg, do_flush=.True.)
    6783              : 
    6784              : 20 continue
    6785            0 :  call xmpi_barrier(comm)
    6786              : 
    6787            0 :  return
    6788              : 
    6789              :  ! Handle Fortran IO error
    6790              : 10 continue
    6791            0 :  ABI_ERROR(msg)
    6792              : 
    6793            0 : end subroutine dvdb_qdownsample
    6794              : !!***
    6795              : 
    6796        38966 : end module m_dvdb
    6797              : !!***
        

Generated by: LCOV version 2.3-1