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-11-09 20:57:54 Functions: 76.0 % 50 38
Branches: 34.0 % 8210 2793

             Branch data     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(one * 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