LCOV - code coverage report
Current view: top level - src/78_eph - m_gstore_converters.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 426 0
Test Date: 2026-11-10 12:08:57 Functions: 0.0 % 6 0
Branches: 0.0 % 1251 0

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_gstore_converters
       2                 :             : !! NAME
       3                 :             : !! m_gstore_converters
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Convert data from gstore.nc to other formats.
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2008-2026 ABINIT group (MG)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_gstore_converters
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_abicore
      26                 :             :  use m_xmpi
      27                 :             :  use m_errors
      28                 :             :  use m_clib
      29                 :             : 
      30                 :             :  use m_io_tools,       only : open_file
      31                 :             :  use m_dtset,          only : dataset_type
      32                 :             :  use m_dtfil,          only : datafiles_type
      33                 :             :  use m_ddb_hdr,        only : ddb_hdr_type
      34                 :             :  use m_hdr,            only : hdr_type
      35                 :             :  use m_fstrings,       only : sjoin, itoa, strcat
      36                 :             :  use m_crystal,        only : crystal_t
      37                 :             :  use m_ebands,         only : ebands_t, gaps_t
      38                 :             :  use m_ifc,            only : ifc_type
      39                 :             :  use m_gstore,         only : gstore_t, GSTORE_GMODE_ATOM, GSTORE_GTYPE_GWPT, gstore_read_gtype
      40                 :             : 
      41                 :             :  implicit none
      42                 :             : 
      43                 :             :  private
      44                 :             : 
      45                 :             :  public :: gstore_convert
      46                 :             :  ! Convert data from gstore.nc to other formats
      47                 :             : 
      48                 :             : !!***
      49                 :             : 
      50                 :             : contains
      51                 :             : !!***
      52                 :             : 
      53                 :             : !----------------------------------------------------------------------
      54                 :             : 
      55                 :             : !!****f* m_gstore_converters/gstore_convert
      56                 :             : !! NAME
      57                 :             : !! gstore_convert
      58                 :             : !!
      59                 :             : !! FUNCTION
      60                 :             : !! Convert data from gstore.nc to other formats
      61                 :             : !!
      62                 :             : !! INPUTS
      63                 :             : !! gstore_path=Filename of the output GSTORE.nc file
      64                 :             : !!
      65                 :             : !! SOURCE
      66                 :             : 
      67                 :           0 : subroutine gstore_convert(gstore_path, dtset, dtfil, cryst, ebands, ifc, comm)
      68                 :             : 
      69                 :             : !Arguments ------------------------------------
      70                 :             : !scalars
      71                 :             :  character(len=*),intent(in) :: gstore_path
      72                 :             :  type(dataset_type),target,intent(in) :: dtset
      73                 :             :  type(datafiles_type),intent(in) :: dtfil
      74                 :             :  class(crystal_t),target,intent(in) :: cryst
      75                 :             :  class(ebands_t),target,intent(in) :: ebands
      76                 :             :  class(ifc_type),target,intent(in) :: ifc
      77                 :             :  integer,intent(in) :: comm
      78                 :             : 
      79                 :             : !Local variables-------------------------------
      80                 :             : !scalars
      81                 :             :  integer :: nprocs, my_rank, nsppol, spin, nmodes, this_comm, unt, ib, nu, i, j, ierr
      82                 :             :  integer :: with_cplex, ik_ibz, my_is, my_ik, my_iq, iq_glob, natom, itypat, lstr_j
      83                 :             :  integer :: ibrav, idir, jdir, iat, ipert, unt_ascii, ik_glob, band_kq, band_k, mu ! jat,
      84                 :             :  logical :: with_g2dw, q_is_gamma, lborn, ascii_write
      85                 :             :  real(dp),parameter :: Ha2Ry = two
      86                 :             :  real(dp) :: weight_qq
      87                 :             :  character(len=5000) :: msg
      88                 :             :  character(len=abi_slen) :: with_gmode, gvals_name, gtype
      89                 :             :  character(len=fnlen) :: fname, fname_ascii, elphmat_dir, prefix
      90                 :             :  character(len=3) :: band_i
      91         [ #  # ]:           0 :  type(gstore_t) :: gstore
      92                 :             : !arrays
      93                 :             :  integer :: units(2)
      94                 :             :  real(dp) :: qpt(3), kk_bz(3), kk_ibz(3), celldm(6)
      95                 :           0 :  real(dp),allocatable :: tau_cart(:,:)
      96                 :           0 :  complex(dp),allocatable :: dyn_qe(:,:), g_cart(:,:,:)
      97         [ #  # ]:           0 :  character(len=3) :: atm(cryst%ntypat)
      98                 :             : !----------------------------------------------------------------------
      99                 :             : 
     100                 :             :  ! Only master works here as performance is not crucial.
     101                 :             :  ! In principle one could activate the q-point/spin parallelism just to distribute
     102                 :             :  ! the memory for the g's to avoid going OOM.
     103                 :           0 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
     104         [ #  # ]:           0 :  if (my_rank /= 0) return
     105                 :             : 
     106         [ #  # ]:           0 :  units = [std_out, ab_out]
     107                 :           0 :  natom = cryst%natom; nmodes = 3 * cryst%natom; nsppol = ebands%nsppol; this_comm = xmpi_comm_self
     108                 :             : 
     109                 :             :  ! QE Bravais lattice metadata.
     110                 :             :  ! We do not classify the QE Bravais lattice from the ABINIT cell, hence ibrav = 0
     111                 :             :  ! (free lattice) and celldm(1) = alat = |a1| in Bohr (the remaining celldm are unused
     112                 :             :  ! for ibrav == 0). The full lattice is otherwise defined by the crystal structure.
     113                 :           0 :  ibrav = 0
     114                 :           0 :  celldm(:) = zero
     115         [ #  # ]:           0 :  celldm(1) = sqrt(sum(cryst%rprimd(:, 1) ** 2))
     116                 :             : 
     117                 :             :  ! Work array for the phonon displacement matrix (per q-point).
     118   [ #  #  #  #  :           0 :  ABI_MALLOC(dyn_qe, (nmodes, nmodes))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     119                 :             : 
     120                 :             :  ! QE tau: ionic positions in Cartesian coordinates, in units of alat (= celldm(1)).
     121   [ #  #  #  #  :           0 :  ABI_MALLOC(tau_cart, (3, natom))
          #  #  #  #  #  
                #  #  # ]
     122         [ #  # ]:           0 :  do iat=1,natom
     123   [ #  #  #  #  :           0 :    tau_cart(:, iat) = matmul(cryst%rprimd, cryst%xred(:, iat)) / celldm(1)
          #  #  #  #  #  
                      # ]
     124                 :             :  end do
     125                 :             : 
     126                 :             :  ! If ascii_write is .True. a human-readable copy of each binary elph.mat.q_* file is
     127                 :             :  ! also written, with the same content (record by record) and a ".ascii" suffix.
     128                 :             :  ! Toggle this flag (or wire it to an input variable) to disable the extra files.
     129                 :             :  ascii_write = .True.
     130                 :           0 :  ascii_write = .False.
     131                 :             : 
     132                 :             :  ! Preliminary consistency check.
     133                 :           0 :  call wrtout(units, sjoin(" Begin conversion GSTORE --> ", dtset%gstore_convert))
     134         [ #  # ]:           0 :  ABI_CHECK(gstore_path /= ABI_NOFILE, sjoin("Invalid gstore_path:", gstore_path))
     135         [ #  # ]:           0 :  ABI_CHECK(dtset%gstore_convert == "epiq", "only gstore_convert == 'epiq' is supported.")
     136                 :             :  !ABI_CHECK(.not. cryst%isalchemical(), "'epiq' format does not support alchemical pseudos.")
     137                 :             : 
     138                 :             :  ! Read g(k,q) from GSTORE and store them in gqk%my_g(nu, im_kq, my_iq, in_k, ik)
     139                 :             :  !
     140                 :             :  ! Shape of array is:
     141                 :             :  !
     142                 :             :  ! (my_npert, nb_kq, my_nq, nb_k, my_nk)
     143                 :             :  ! (       p, b1_kq,     q, b2_k, k)  -->  <k+q, b1| D_{q,p}H |k, b2>
     144                 :             : 
     145                 :             :  ! The g's are complex and in the phonon representation.
     146                 :             :  ! Note <k+q| for the final state and |k> for the initial state. I guess epiq uses the same convention.
     147                 :             :  ! All quantities are in atomic units (Hartree and Bohr).
     148                 :             :  !
     149                 :             :  ! The gstore file produced by the GWPT code has both GWPT and KS g.
     150                 :             :  ! In this case, we convert the GWPT matrix elements but one can still select
     151                 :             :  ! the KS e-ph vertex via gstore_gname.
     152                 :             : 
     153                 :           0 :  call gstore_read_gtype(gstore_path, gtype, this_comm)
     154                 :           0 :  gvals_name = "gvals"
     155   [ #  #  #  # ]:           0 :  if (gtype == GSTORE_GTYPE_GWPT .and. dtset%gstore_gname == "gvals_ks") gvals_name = "gvals_ks"
     156                 :             : 
     157                 :             :  ! Request the ATOM representation: gstore.nc stores g in this representation (the bare
     158                 :             :  ! deformation potential w.r.t. reduced atomic displacements), so no atom->phonon
     159                 :             :  ! conversion is performed. This avoids ephtk_gkknu_from_atm, which would otherwise zero
     160                 :             :  ! the acoustic/imaginary modes (phfrq < EPHTK_WTOL) and divide by sqrt(2*omega).
     161                 :           0 :  with_cplex = 2; with_gmode = GSTORE_GMODE_ATOM; with_g2dw = .False.
     162                 :             : 
     163                 :             :  call gstore%from_ncpath(gstore_path, with_cplex, dtset, dtfil, cryst, ebands, ifc, &
     164                 :           0 :                          with_gmode, gvals_name, with_g2dw, this_comm)
     165                 :             : 
     166                 :             :  ! Consistency check.
     167         [ #  # ]:           0 :  ABI_CHECK(nsppol == 1, "Don't know how to convert spin-polarized g to epiq format!")
     168                 :             : 
     169                 :             :  ! For wannierization, we need the same number of bands for m and n.
     170                 :             :  ! Also, k and q must be in the BZ without any filter.
     171                 :             :  ! Once the symmetrization of the g's has been implemented, this routine
     172                 :             :  ! will receive a gstore file in which all g(k,q) matrix elements in the BZ
     173                 :             :  ! have been reconstructed using symmetry operations.
     174         [ #  # ]:           0 :  ABI_CHECK(gstore%same_nbands(msg), msg)
     175         [ #  # ]:           0 :  if (gstore%check_cplex_qkzone_gmode(2, "bz", "bz", "atom", kfilter="none") /= 0) then
     176                 :           0 :    ABI_ERROR("GSTORE.nc should have both k and q in the full BZ. See messages above.")
     177                 :             :  end if
     178                 :             : 
     179                 :             :  ! Create directory to store output files.
     180                 :           0 :  prefix = "epiq"
     181         [ #  # ]:           0 :  elphmat_dir = strcat(dtfil%filnam_ds(4), "_", prefix)
     182                 :           0 :  call wrtout(units, sjoin(" Output files written to directory:", elphmat_dir))
     183                 :           0 :  call execute_command_line(sjoin("rm -rf", elphmat_dir), exitstat=ierr)
     184                 :           0 :  call clib_mkdir_if_needed(elphmat_dir, ierr)
     185         [ #  # ]:           0 :  ABI_CHECK(ierr == 0, "mkdir returned ierr /= 0")
     186                 :             : 
     187                 :             :  ! Write the EPIQ input namelist (&Diff_Start_Param + KPOINTS), the analog of QE's
     188                 :             :  ! print_ph_input2epiq called inside ep_matrix_element_wannier.
     189                 :           0 :  call write_epiq_input(ebands, dtfil, strcat(elphmat_dir, "/scf_dfpt.2epiq.in"))
     190                 :           0 :  call wrtout(units, sjoin(" EPIQ input namelist written to:", strcat(elphmat_dir, "/scf_dfpt.2epiq.in")))
     191                 :             : 
     192                 :             :  ! Write the dynq0 file: q-mesh, number of irreducible q-points and their positions
     193                 :             :  ! in Cartesian coordinates (2pi/alat), the analog of QE's dynq0 output.
     194                 :           0 :  call write_dynq0(gstore%ngqpt, gstore%qibz, cryst%gprimd, celldm(1), strcat(elphmat_dir, "/dynq0"))
     195                 :           0 :  call wrtout(units, sjoin(" EPIQ dynq0 file written to:", strcat(elphmat_dir, "/dynq0")))
     196                 :             : 
     197                 :             :  ! NB: atm is character(len=3) while symbol_type returns character(len=2).
     198         [ #  # ]:           0 :  do itypat=1, cryst%ntypat
     199                 :           0 :    atm(itypat)(1:2) = cryst%symbol_type(itypat)
     200                 :           0 :    atm(itypat)(3:3) = ""
     201                 :             :  end do
     202                 :             : 
     203                 :             :  ! Write one dynamical-matrix file (dynq<iq>) per irreducible q-point, in QE format
     204                 :             :  ! (same ordering as the dynq0 list).
     205         [ #  # ]:           0 :  do iq_glob=1,gstore%nqibz
     206                 :             :    call write_dynq(cryst, ifc, gstore%qibz(:,iq_glob), celldm(1), atm, &
     207                 :           0 :                    strcat(elphmat_dir, "/dynq", itoa(iq_glob)))
     208                 :             :  end do
     209                 :           0 :  call wrtout(units, sjoin(" EPIQ dynq<iq> dynamical-matrix files written to directory:", elphmat_dir))
     210                 :             : 
     211                 :             :  ! TODO: Need helper function to get ibrav, celldm from crystal
     212                 :             :  ! Some input from the EPIC developers would be greatly appreciated.
     213                 :             :  !call cryst%get_ibrav_celldm(ibrav, celldm)
     214                 :             : 
     215                 :             :  ! Loop over collinear spins.
     216         [ #  # ]:           0 :  do my_is=1,gstore%my_nspins
     217                 :           0 :    spin = gstore%my_spins(my_is)
     218                 :           0 :    associate (gqk => gstore%gqk(my_is))
     219                 :             : 
     220                 :             :    ! Buffer for the e-ph matrix elements rotated to the Cartesian atomic-displacement basis.
     221   [ #  #  #  #  :           0 :    ABI_MALLOC(g_cart, (nmodes, gqk%nb_kq, gqk%nb_k))
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     222                 :             : 
     223                 :             :    !num_bands = gqk%nb_k
     224                 :             : 
     225                 :             :    ! Loop over q-points in the BZ.
     226         [ #  # ]:           0 :    do my_iq=1, gqk%my_nq
     227                 :           0 :      iq_glob = my_iq + gqk%my_qstart - 1
     228                 :             : 
     229                 :           0 :      call gqk%myqpt(my_iq, gstore, weight_qq, qpt); q_is_gamma = sum(qpt**2) < tol14
     230                 :           0 :      call define_band_string(iq_glob, band_i, lstr_j)
     231                 :             : 
     232         [ #  # ]:           0 :      fname = trim(elphmat_dir)//"/"//trim(prefix)//'_elph.mat.q_'//band_i(1:lstr_j)
     233         [ #  # ]:           0 :      if (open_file(fname, msg, newunit=unt, form="unformatted", status="unknown", action="write") /= 0) then
     234                 :           0 :        ABI_ERROR(msg)
     235                 :             :      end if
     236                 :             : 
     237                 :             :      ! Optional human-readable companion file with the same content.
     238         [ #  # ]:           0 :      if (ascii_write) then
     239         [ #  # ]:           0 :        fname_ascii = trim(fname)//".ascii"
     240         [ #  # ]:           0 :        if (open_file(fname_ascii, msg, newunit=unt_ascii, form="formatted", status="unknown", action="write") /= 0) then
     241                 :           0 :          ABI_ERROR(msg)
     242                 :             :        end if
     243                 :             :      end if
     244                 :             : 
     245                 :             :      ! EPIQ format. See https://gitlab.com/the-epiq-team/epiq/-/blob/develop/src/io_matelem.F90
     246                 :             :      !read(unt) (xq_r(j),j=1,3)
     247                 :             :      !if (.not.fet) read(unt) noncolin, nspin, lborn !REMOVE FOR VERSION 5.1 FET
     248                 :             :      !read(unt) nel_aux
     249                 :             :      !read(unt) nbnd_min, nbnd_max, nbnd_r !nbnd_r = total number of bands in pw
     250                 :             :      !read(unt) nmodes, nk_r, nat, ntyp
     251                 :             :      !read(unt) ibrav,(celldm(j), j=1,6)
     252                 :             :      !read(unt) (atm(j),j=1,ntyp),(amass(j),j=1,ntyp), &
     253                 :             :      !           (ityp(j),j=1,nat),((tau(j,i),j=1,3),i=1,nat)
     254                 :             :      !read(unt) (w2 (nu,iqph) , nu=1,nmodes)
     255                 :             :      !read(unt) ((zz(i,j,iqph), i=1,nmodes),j=1,nmodes)   !eigenvectors in the QE basis
     256                 :             :      !read(unt) ((dyn(i,j,iqph),i=1,nmodes),j=1,nmodes)  ! eigenvectors divided by masses
     257                 :             :      !do k=1,num_kpts
     258                 :             :      !  read(unt) (xk_r(i,k),i=1,3)
     259                 :             :      !  read(unt) (eig(i,k),i=1,num_bands)
     260                 :             :      !  do nu=1,nmodes
     261                 :             :      !    write(unt) ((g_matrix(j, i, nu, k, iq),j=1,num_bands),i=1,num_bands)
     262                 :             :      !  end do
     263                 :             :      !end do
     264                 :             : 
     265                 :             :      ! Conventions used below (matched to QE pw/PHonon elphsum_wannier and the EPIQ reader):
     266                 :             :      ! - w2 is omega^2 (squared phonon frequency) in Ry^2, signed (< 0 for imaginary modes).
     267                 :             :      ! - lborn = .False.: BECS / dynamical quadrupoles are not exported yet.
     268                 :             :      ! - tau are atom positions in Cartesian coordinates, in units of alat (= xcart/alat).
     269                 :             :      ! - nel_aux (ebands%nelect) is the (real) number of electrons including possible doping.
     270                 :             :      ! - The e-ph matrix elements are written in the Cartesian atomic-displacement basis
     271                 :             :      !   (as in QE ep_matrix_element_wannier). gstore provides g in the atom representation
     272                 :             :      !   w.r.t. *reduced* atomic displacements; we rotate it to Cartesian directions with
     273                 :             :      !   gprimd (a per-atom 3x3 map). No mode/frequency factors are involved, so no mode is
     274                 :             :      !   zeroed. Consequently zz (the QE pattern matrix) is the identity, while dyn keeps the
     275                 :             :      !   Cartesian phonon displacements (= my_displ_cart).
     276                 :           0 :      lborn = .False.
     277                 :             : 
     278                 :             :      ! Record 1: q-point in reduced (crystal) coordinates.
     279                 :           0 :      write(unt) qpt
     280         [ #  # ]:           0 :      if (ascii_write) then
     281                 :           0 :        write(unt_ascii, '(a)') "# Record 1: q-point (reduced coordinates)"
     282                 :           0 :        write(unt_ascii, '(3es24.15)') qpt
     283                 :             :      end if
     284                 :             : 
     285                 :             :      ! Record 2: noncolin, nspin, lborn. BECS/quadrupoles not exported yet => lborn = .False.
     286                 :           0 :      write(unt) ebands%nspinor == 2, nsppol, lborn
     287         [ #  # ]:           0 :      if (ascii_write) then
     288                 :           0 :        write(unt_ascii, '(a)') "# Record 2: noncolin, nspin, lborn"
     289                 :           0 :        write(unt_ascii, *) ebands%nspinor == 2, nsppol, lborn
     290                 :             :      end if
     291                 :             : 
     292                 :             :      ! Record 3: number of electrons (including possible doping).
     293                 :           0 :      write(unt) ebands%nelect
     294         [ #  # ]:           0 :      if (ascii_write) then
     295                 :           0 :        write(unt_ascii, '(a)') "# Record 3: number of electrons"
     296                 :           0 :        write(unt_ascii, '(es24.15)') ebands%nelect
     297                 :             :      end if
     298                 :             : 
     299                 :             :      ! Record 4: first band, last band, total number of bands in the pw calculation.
     300                 :           0 :      write(unt) gqk%bstart_k, gqk%bstop_k, ebands%mband
     301         [ #  # ]:           0 :      if (ascii_write) then
     302                 :           0 :        write(unt_ascii, '(a)') "# Record 4: nbnd_min, nbnd_max, nbnd_total"
     303                 :           0 :        write(unt_ascii, '(3i8)') gqk%bstart_k, gqk%bstop_k, ebands%mband
     304                 :             :      end if
     305                 :             : 
     306                 :             :      ! Record 5: number of modes, number of k-points, number of atoms, number of atom types.
     307                 :           0 :      write(unt) nmodes, gqk%glob_nk, natom, cryst%ntypat
     308         [ #  # ]:           0 :      if (ascii_write) then
     309                 :           0 :        write(unt_ascii, '(a)') "# Record 5: nmodes, nkpt, natom, ntypat"
     310                 :           0 :        write(unt_ascii, '(4i8)') nmodes, gqk%glob_nk, natom, cryst%ntypat
     311                 :             :      end if
     312                 :             : 
     313                 :             :      ! Record 6: Bravais lattice index and cell dimensions (see ibrav/celldm comment above).
     314                 :           0 :      write(unt) ibrav, (celldm(j), j=1,6)
     315         [ #  # ]:           0 :      if (ascii_write) then
     316                 :           0 :        write(unt_ascii, '(a)') "# Record 6: ibrav, celldm(1:6)"
     317                 :           0 :        write(unt_ascii, '(i6,6es24.15)') ibrav, (celldm(j), j=1,6)
     318                 :             :      end if
     319                 :             : 
     320                 :             :      ! Record 7: atom symbols, atomic masses (atomic mass unit), atom types and
     321                 :             :      !           Cartesian atomic positions tau in units of alat.
     322         [ #  # ]:           0 :      write(unt) (atm(j), j=1,cryst%ntypat), (cryst%amu(j), j=1,cryst%ntypat), &
     323   [ #  #  #  #  :           0 :                 (cryst%typat(j), j=1,natom), ((tau_cart(j,i), j=1,3), i=1,natom)
                   #  # ]
     324         [ #  # ]:           0 :      if (ascii_write) then
     325                 :           0 :        write(unt_ascii, '(a)') "# Record 7: atom symbols, masses (amu), types, tau (Cartesian, alat units)"
     326                 :           0 :        write(unt_ascii, '(*(a3,1x))') (atm(j), j=1,cryst%ntypat)
     327   [ #  #  #  # ]:           0 :        write(unt_ascii, '(*(es24.15,1x))') (cryst%amu(j), j=1,cryst%ntypat)
     328   [ #  #  #  # ]:           0 :        write(unt_ascii, '(*(i6,1x))') (cryst%typat(j), j=1,natom)
     329         [ #  # ]:           0 :        do i=1,natom
     330                 :           0 :          write(unt_ascii, '(3es24.15)') (tau_cart(j,i), j=1,3)
     331                 :             :        end do
     332                 :             :      end if
     333                 :             : 
     334                 :             :      ! Record 8: squared phonon frequencies omega^2 in Ry^2.
     335                 :             :      ! my_wnuq is the signed frequency omega in Ha (negative for imaginary modes), so
     336                 :             :      ! omega^2 = sign(omega) * (omega*Ha2Ry)^2 = omega*|omega|*Ha2Ry^2, matching QE's w2.
     337   [ #  #  #  # ]:           0 :      write(unt) (gqk%my_wnuq(nu, my_iq) * abs(gqk%my_wnuq(nu, my_iq)) * Ha2Ry ** 2, nu=1,nmodes)
     338         [ #  # ]:           0 :      if (ascii_write) then
     339                 :           0 :        write(unt_ascii, '(a)') "# Record 8: phonon frequencies squared omega^2 (Ry^2)"
     340                 :             :        write(unt_ascii, '(*(es24.15,1x))') &
     341   [ #  #  #  # ]:           0 :          (gqk%my_wnuq(nu, my_iq) * abs(gqk%my_wnuq(nu, my_iq)) * Ha2Ry ** 2, nu=1,nmodes)
     342                 :             :      end if
     343                 :             : 
     344                 :             :      ! Phonon displacements for this q-point (composite index ipert = idir + 3*(iat-1),
     345                 :             :      ! Cartesian direction fast, atom slow, matching the QE mode/perturbation ordering):
     346                 :             :      !   dyn_qe = phonon displacements (eigenvectors divided by sqrt(mass)) = my_displ_cart.
     347                 :             :      ! These are written as 'dyn' (record 10) and used below to rotate g to the Cartesian basis.
     348                 :             :      !do iat=1,natom
     349                 :             :        !do idir=1,3
     350                 :             :          !mu = (iat-1)*3+idir
     351                 :             :          !do jat=1,natom
     352                 :             :            !do jdir=1,3
     353                 :             :              !nu = (jat-1)*3+jdir
     354                 :             :              !dyn_qe(mu, nu) = cmplx(gstore%ifc_dynmat(1,idir,iat,jdir,jat),&
     355                 :             :                !gstore%ifc_dynmat(2,idir,iat,jdir,jat),kind=dp)
     356                 :             :            !end do
     357                 :             :          !end do
     358                 :             :        !end do
     359                 :             :      !end do
     360         [ #  # ]:           0 :      do nu=1,nmodes
     361         [ #  # ]:           0 :        do iat=1,natom
     362         [ #  # ]:           0 :          do idir=1,3
     363                 :           0 :            ipert = idir + 3 * (iat - 1)
     364                 :             :            dyn_qe(ipert, nu) = cmplx(gqk%my_displ_cart(1, idir, iat, nu, my_iq), &
     365                 :           0 :                                      gqk%my_displ_cart(2, idir, iat, nu, my_iq), kind=dp)
     366                 :             :          end do
     367                 :             :        end do
     368                 :             :      end do
     369                 :             : 
     370                 :             :      ! Record 9: eigenvectors in the QE basis (zz).
     371                 :             :      ! Like QE's ep_matrix_element_wannier, the e-ph matrix elements are written in the
     372                 :             :      ! Cartesian (atomic-displacement) basis (see the rotation in the k-loop below), so the
     373                 :             :      ! QE pattern matrix u reduces to the identity. We therefore write the identity matrix.
     374   [ #  #  #  #  :           0 :      write(unt) ((cmplx(merge(one, zero, i == j), zero, kind=dp), i=1,nmodes), j=1,nmodes)
          #  #  #  #  #  
                      # ]
     375         [ #  # ]:           0 :      if (ascii_write) then
     376                 :           0 :        write(unt_ascii, '(a)') "# Record 9: eigenvectors in the QE basis zz = identity (Cartesian g)"
     377         [ #  # ]:           0 :        do j=1,nmodes
     378         [ #  # ]:           0 :          do i=1,nmodes
     379         [ #  # ]:           0 :            write(unt_ascii, '(2i6,2es24.15)') i, j, cmplx(merge(one, zero, i == j), zero, kind=dp)
     380                 :             :          end do
     381                 :             :        end do
     382                 :             :      end if
     383                 :             : 
     384                 :             :      ! Record 10: eigenvectors divided by masses, i.e. phonon displacements (dyn).
     385                 :           0 :      write(unt) ((dyn_qe(i, j), i=1,nmodes), j=1,nmodes)
     386         [ #  # ]:           0 :      if (ascii_write) then
     387                 :           0 :        write(unt_ascii, '(a)') "# Record 10: displacements dyn(component, mode)"
     388         [ #  # ]:           0 :        do j=1,nmodes
     389         [ #  # ]:           0 :          do i=1,nmodes
     390                 :           0 :            write(unt_ascii, '(2i6,2es24.15)') i, j, dyn_qe(i, j)
     391                 :             :          end do
     392                 :             :        end do
     393                 :             :      end if
     394                 :             : 
     395                 :             :      ! Records 11+: per k-point, the k-point (reduced coords), band energies (Ry) and,
     396                 :             :      !              for each Cartesian atomic perturbation, the e-ph matrix elements g (Ry).
     397         [ #  # ]:           0 :      do my_ik=1,gqk%my_nk
     398         [ #  # ]:           0 :        kk_bz = gqk%my_kpts(:, my_ik)
     399                 :           0 :        ik_ibz = gqk%my_k2ibz(1, my_ik)
     400                 :           0 :        kk_ibz = ebands%kptns(:,ik_ibz)
     401                 :           0 :        ik_glob = my_ik + gqk%my_kstart - 1
     402                 :             : 
     403                 :           0 :        write(unt) kk_bz
     404   [ #  #  #  # ]:           0 :        write(unt) (ebands%eig(ib, ik_ibz, spin) * Ha2Ry, ib=gqk%bstart_k, gqk%bstop_k)
     405         [ #  # ]:           0 :        if (ascii_write) then
     406                 :           0 :          write(unt_ascii, '(a,i0,a)') "# k-point ", ik_glob, " (reduced coordinates)"
     407                 :           0 :          write(unt_ascii, '(3es24.15)') kk_bz
     408                 :           0 :          write(unt_ascii, '(a)') "#   band energies (Ry)"
     409   [ #  #  #  # ]:           0 :          write(unt_ascii, '(*(es24.15,1x))') (ebands%eig(ib, ik_ibz, spin) * Ha2Ry, ib=gqk%bstart_k, gqk%bstop_k)
     410                 :             :        end if
     411                 :             : 
     412                 :             :        ! Rotate g from the atom representation (reduced atomic-displacement directions, as
     413                 :             :        ! stored in gstore) to Cartesian directions, giving the bare Cartesian deformation
     414                 :             :        ! potential expected by EPIQ:
     415                 :             :        !   d_cart(beta,kappa) = sum_alpha gprimd(beta,alpha) * g_red(alpha,kappa)
     416                 :             :        ! with the composite index mu = idir + 3*(iat-1). This is a per-atom 3x3 map: it
     417                 :             :        ! involves no frequency or mass factors, so every mode is preserved (nothing is
     418                 :             :        ! zeroed, unlike the atom->phonon->Cartesian path). The Ha->Ry factor is applied
     419                 :             :        ! on output below, hence d_cart is in Ry/Bohr there.
     420   [ #  #  #  #  :           0 :        g_cart = (zero, zero)
                   #  # ]
     421         [ #  # ]:           0 :        do iat=1,natom
     422         [ #  # ]:           0 :          do idir=1,3                   ! Cartesian direction beta
     423                 :           0 :            mu = idir + 3 * (iat - 1)
     424         [ #  # ]:           0 :            do jdir=1,3                 ! reduced direction alpha
     425                 :           0 :              ipert = jdir + 3 * (iat - 1)
     426                 :             :              g_cart(mu, :, :) = g_cart(mu, :, :) &
     427   [ #  #  #  # ]:           0 :                + cryst%gprimd(idir, jdir) * gqk%my_g(ipert, :, my_iq, :, my_ik)
     428                 :             :            end do
     429                 :             :          end do
     430                 :             :        end do
     431                 :             : 
     432         [ #  # ]:           0 :        do mu=1,nmodes
     433                 :             :          ! d_matrix(m, n) = <k+q, m| dV/du^cart_mu |k, n>, with the k+q (bra) band index m
     434                 :             :          ! running fastest, matching QE's el_ph_mat(jbnd, ibnd) write order.
     435                 :             :          ! The 2nd dim (nb_kq) is the k+q band, the 3rd dim (nb_k) the k band.
     436   [ #  #  #  #  :           0 :          write(unt) ((g_cart(mu, j, i) * Ha2Ry, j=1,gqk%nb_kq), i=1,gqk%nb_k)
             #  #  #  # ]
     437         [ #  # ]:           0 :          if (ascii_write) then
     438                 :             :            ! Columns: k index, Cartesian perturbation, band(k+q), band(k), Re(d), Im(d) in Ry.
     439         [ #  # ]:           0 :            do i=1,gqk%nb_k
     440                 :           0 :              band_k = i + gqk%bstart_k - 1
     441         [ #  # ]:           0 :              do j=1,gqk%nb_kq
     442                 :           0 :                band_kq = j + gqk%bstart_kq - 1
     443                 :             :                write(unt_ascii, '(4i6,2es30.15)') &
     444                 :           0 :                  ik_glob, mu, band_kq, band_k, g_cart(mu, j, i) * Ha2Ry
     445                 :             :              end do
     446                 :             :            end do
     447                 :             :          end if
     448                 :             :        end do
     449                 :             :      end do ! my_ik
     450                 :             : 
     451                 :             :      ! Trailing block: symmetry operations and star of q (QE elphsum_wannier layout).
     452                 :           0 :      call write_qe_symmetry(cryst, qpt, celldm(1), unt, ascii_write, unt_ascii)
     453                 :             : 
     454                 :           0 :      close(unt)
     455         [ #  # ]:           0 :      if (ascii_write) close(unt_ascii)
     456                 :             :    end do ! my_iq
     457                 :             : 
     458   [ #  #  #  # ]:           0 :    ABI_FREE(g_cart)
     459                 :             :    end associate
     460                 :             :  end do ! spin
     461                 :             : 
     462                 :             :  ! TODO:
     463                 :             :  ! Output BECS, dynamical quadrupoles, dynamical matrix, group velocities
     464                 :             :  ! See m_ifc
     465                 :             :  !ifc%zeff
     466                 :             :  !fc%qdrp_cart
     467                 :             :  !ifc%eta
     468                 :             :  !ifc%rpt
     469                 :             :  !ifc%wghatm
     470                 :             :  !ifc%dynmat
     471                 :             :  !ifc%short_atmfrc
     472                 :             : 
     473         [ #  # ]:           0 :  ABI_FREE(dyn_qe)
     474         [ #  # ]:           0 :  ABI_FREE(tau_cart)
     475                 :             : 
     476                 :           0 :  call gstore%free()
     477                 :             : 
     478   [ #  #  #  #  :           0 : end subroutine gstore_convert
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     479                 :             : !!***
     480                 :             : 
     481                 :             : !----------------------------------------------------------------------
     482                 :             : 
     483                 :             : !!****f* m_gstore_converters/write_epiq_input
     484                 :             : !! NAME
     485                 :             : !! write_epiq_input
     486                 :             : !!
     487                 :             : !! FUNCTION
     488                 :             : !!  Write the EPIQ input file with the &Diff_Start_Param namelist and the KPOINTS
     489                 :             : !!  section, reproducing QE's print_ph_input2epiq (called from ep_matrix_element_wannier).
     490                 :             : !!  The SCF/DFPT parameters are taken from the ABINIT dataset and band structure.
     491                 :             : !!
     492                 :             : !! INPUTS
     493                 :             : !!  ebands<ebands_t>=band structure (only used for HOMO/LUMO of insulators).
     494                 :             : !!  dtfil<datafiles_type>=filenames; dtfil%fildvdbin (DVDB) and dtfil%filddbsin (DDB).
     495                 :             : !!  fname=name of the output file.
     496                 :             : !!
     497                 :             : !! NOTES
     498                 :             : !!  ALL exported parameters come from the calculation that produced the DDB/DVDB
     499                 :             : !!  (the ground-state/DFPT run), NOT from the (denser) gstore/eph run:
     500                 :             : !!   - efermi, nel_r, occopt (-> ngauss_ph), tsmear (-> sigma_ph) from the DVDB header
     501                 :             : !!     (a standard ABINIT header carrying the GS scalars including the Fermi level).
     502                 :             : !!   - the KPOINTS list from the DDB header (the GS/DFPT k-mesh).
     503                 :             : !!  Exception: HOMO/LUMO of insulators are not stored in either header (no GS
     504                 :             : !!  eigenvalues), so they are taken from ebands (gap edges, essentially mesh-independent).
     505                 :             : !!
     506                 :             : !! SOURCE
     507                 :             : 
     508                 :           0 : subroutine write_epiq_input(ebands, dtfil, fname)
     509                 :             : 
     510                 :             : !Arguments ------------------------------------
     511                 :             :  class(ebands_t),intent(in) :: ebands
     512                 :             :  type(datafiles_type),intent(in) :: dtfil
     513                 :             :  character(len=*),intent(in) :: fname
     514                 :             : 
     515                 :             : !Local variables-------------------------------
     516                 :             : !scalars
     517                 :             :  integer :: unt, iunt, ik, ngauss, gap_err, fform
     518                 :             :  real(dp) :: homo, lumo, knorm
     519                 :             :  logical :: is_metal
     520                 :             :  character(len=500) :: msg
     521                 :             :  character(len=24) :: smear_label
     522                 :           0 :  type(gaps_t) :: gaps
     523   [ #  #  #  #  :           0 :  type(ddb_hdr_type) :: ddb_hdr
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     524                 :           0 :  type(hdr_type) :: dfpt_hdr
     525                 :             : !----------------------------------------------------------------------
     526                 :             : 
     527         [ #  # ]:           0 :  if (open_file(fname, msg, newunit=unt, form="formatted", status="unknown", action="write") /= 0) then
     528                 :           0 :    ABI_ERROR(msg)
     529                 :             :  end if
     530                 :             : 
     531                 :             :  ! Read the GS/DFPT header from the DVDB: it carries the Fermi level, nelect, occopt
     532                 :             :  ! and tsmear of the run that produced the DDB/DVDB (the DDB header has no Fermi level).
     533                 :             :  ! The DVDB starts with two records (version, numv1) before the standard ABINIT header,
     534                 :             :  ! so we skip them and read the header in place (fort_read without rewind).
     535         [ #  # ]:           0 :  if (open_file(dtfil%fildvdbin, msg, newunit=iunt, form="unformatted", status="old", action="read") /= 0) then
     536                 :           0 :    ABI_ERROR(msg)
     537                 :             :  end if
     538                 :           0 :  read(iunt)   ! skip the DVDB version record
     539                 :           0 :  read(iunt)   ! skip the numv1 record
     540                 :           0 :  call dfpt_hdr%fort_read(iunt, fform)
     541                 :           0 :  close(iunt)
     542                 :             : 
     543                 :             :  ! occopt >= 3 => metallic occupation with smearing; otherwise fixed occupations (insulator).
     544                 :           0 :  is_metal = dfpt_hdr%occopt >= 3
     545                 :             : 
     546                 :           0 :  write(unt, '(a)') "! parameter of the SCF DFPT calculation useful for EPIq"
     547                 :           0 :  write(unt, '(a)') "&Diff_Start_Param"
     548                 :           0 :  write(unt, '(3x,a,f12.6,a)') "efermi=", dfpt_hdr%fermie * Ha_eV, ", ! in (eV)"
     549                 :           0 :  write(unt, '(3x,a,f12.6,a)') "nel_r=", dfpt_hdr%nelect, ","
     550                 :             : 
     551         [ #  # ]:           0 :  if (.not. is_metal) then
     552                 :             :    ! Insulator: report the HOMO and LUMO levels (in eV). Not in the DFPT header
     553                 :             :    ! (no GS eigenvalues), so taken from ebands (gap edges are mesh-independent).
     554                 :           0 :    gaps = ebands%get_gaps(gap_err)
     555         [ #  # ]:           0 :    if (gap_err == 0) then
     556                 :           0 :      homo = gaps%vb_max(1); lumo = gaps%cb_min(1)
     557                 :             :    else
     558                 :             :      ! Could not determine a gap (semimetal?): fall back to the Fermi level.
     559                 :             :      homo = dfpt_hdr%fermie; lumo = dfpt_hdr%fermie
     560                 :             :    end if
     561                 :           0 :    call gaps%free()
     562                 :           0 :    write(unt, '(3x,a,f12.6,a)') "homo=", homo * Ha_eV, ", ! in (eV)"
     563                 :           0 :    write(unt, '(3x,a,f12.6,a)') "lumo=", lumo * Ha_eV, ", ! in (eV)"
     564                 :             :  else
     565                 :             :    ! Metal: report the smearing width (Rydberg) and the QE ngauss code.
     566                 :             :    ! Map ABINIT occopt onto QE ngauss (see Modules input conventions):
     567                 :             :    !   3 -> -99 (Fermi-Dirac), 4/5 -> -1 (cold/Marzari), 6 -> 1 (Methfessel-Paxton), 7 -> 0 (Gaussian)
     568                 :           0 :    select case (dfpt_hdr%occopt)
     569                 :           0 :    case (3);        ngauss = -99; smear_label = "fd"
     570                 :           0 :    case (4, 5);     ngauss =  -1; smear_label = "cold"
     571                 :           0 :    case (6);        ngauss =   1; smear_label = "mp"
     572                 :           0 :    case (7);        ngauss =   0; smear_label = "gauss"
     573   [ #  #  #  #  :           0 :    case default;    ngauss = -66; smear_label = "unknown"
                      # ]
     574                 :             :    end select
     575                 :           0 :    write(unt, '(3x,a,f12.6,a)') "sigma_ph=", dfpt_hdr%tsmear * two, ", ! in (Rydberg)"
     576                 :           0 :    write(unt, '(3x,a,i3,a)') "ngauss_ph=", ngauss, ", ! "//trim(smear_label)
     577                 :             :  end if
     578                 :           0 :  write(unt, '(a)') "/"
     579                 :             : 
     580                 :           0 :  call dfpt_hdr%free()
     581                 :             : 
     582                 :             :  ! KPOINTS section. Use the k-mesh that produced the DDB/DVDB (the ground-state/DFPT
     583                 :             :  ! mesh), read from the DDB header, NOT the gstore/eph k-mesh in dtset/ebands.
     584                 :             :  ! The DDB header stores the explicit k-point list (no kptrlatt), so we dump it.
     585                 :           0 :  call ddb_hdr%open_read(dtfil%filddbsin, xmpi_comm_self)
     586                 :           0 :  call ddb_hdr%close()   ! we only need the header data (k-points)
     587                 :             : 
     588         [ #  # ]:           0 :  knorm = ddb_hdr%kptnrm; if (abs(knorm) < tol12) knorm = one
     589                 :             : 
     590                 :           0 :  write(unt, '(/,a)') "KPOINTS"
     591                 :           0 :    write(unt, '(a)') "crystal"
     592                 :           0 :  write(unt, '(6x,i9)') ddb_hdr%nkpt
     593         [ #  # ]:           0 :  do ik=1,ddb_hdr%nkpt
     594         [ #  # ]:           0 :    write(unt, '(3x,4(es20.10,2x))') ddb_hdr%kpt(:,ik) / knorm, ddb_hdr%wtk(ik)
     595                 :             :    end do
     596                 :             : 
     597                 :           0 :  call ddb_hdr%free()
     598                 :             : 
     599                 :           0 :  close(unt)
     600                 :             : 
     601   [ #  #  #  #  :           0 : end subroutine write_epiq_input
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     602                 :             : !!***
     603                 :             : 
     604                 :             : !----------------------------------------------------------------------
     605                 :             : 
     606                 :             : !!****f* m_gstore_converters/write_dynq0
     607                 :             : !! NAME
     608                 :             : !! write_dynq0
     609                 :             : !!
     610                 :             : !! FUNCTION
     611                 :             : !!  Write the EPIQ "dynq0" file: the q-mesh, the number of irreducible q-points
     612                 :             : !!  contained in the elph.mat files, and the list of those q-points in Cartesian
     613                 :             : !!  coordinates (units of 2pi/alat, i.e. QE tpiba). Analog of QE's dynq0 output.
     614                 :             : !!
     615                 :             : !! INPUTS
     616                 :             : !!  ngqpt(3)=dimensions of the q-mesh.
     617                 :             : !!  qibz(3,nqibz)=irreducible q-points in reduced (crystal) coordinates.
     618                 :             : !!  gprimd(3,3)=reciprocal lattice vectors (Bohr^-1), columns G_i/2pi (ABINIT convention).
     619                 :             : !!  alat=lattice parameter in Bohr (celldm(1)).
     620                 :             : !!  fname=name of the output file.
     621                 :             : !!
     622                 :             : !! SOURCE
     623                 :             : 
     624         [ #  # ]:           0 : subroutine write_dynq0(ngqpt, qibz, gprimd, alat, fname)
     625                 :             : 
     626                 :             : !Arguments ------------------------------------
     627                 :             :  integer,intent(in) :: ngqpt(3)
     628                 :             :  real(dp),intent(in) :: qibz(:,:), gprimd(3,3), alat
     629                 :             :  character(len=*),intent(in) :: fname
     630                 :             : 
     631                 :             : !Local variables-------------------------------
     632                 :             :  integer :: unt, iq, nqibz
     633                 :             :  real(dp) :: qcart(3)
     634                 :             :  character(len=500) :: msg
     635                 :             : !----------------------------------------------------------------------
     636                 :             : 
     637                 :           0 :  nqibz = size(qibz, 2)
     638                 :             : 
     639         [ #  # ]:           0 :  if (open_file(fname, msg, newunit=unt, form="formatted", status="unknown", action="write") /= 0) then
     640                 :           0 :    ABI_ERROR(msg)
     641                 :             :  end if
     642                 :             : 
     643                 :             :  ! Line 1: q-mesh. Line 2: number of irreducible q-points.
     644                 :           0 :  write(unt, '(3i4)') ngqpt(1), ngqpt(2), ngqpt(3)
     645                 :           0 :  write(unt, '(i4)') nqibz
     646                 :             : 
     647                 :             :  ! One line per irreducible q-point in Cartesian coordinates (2pi/alat units):
     648                 :             :  ! q_cart[tpiba] = alat * matmul(gprimd, q_red).
     649         [ #  # ]:           0 :  do iq=1,nqibz
     650   [ #  #  #  #  :           0 :    qcart = alat * matmul(gprimd, qibz(:,iq))
                   #  # ]
     651                 :           0 :    write(unt, '(3e24.15)') qcart(1), qcart(2), qcart(3)
     652                 :             :  end do
     653                 :             : 
     654                 :           0 :  close(unt)
     655                 :             : 
     656                 :           0 : end subroutine write_dynq0
     657                 :             : !!***
     658                 :             : 
     659                 :             : !----------------------------------------------------------------------
     660                 :             : 
     661                 :             : !!****f* m_gstore_converters/write_dynq
     662                 :             : !! NAME
     663                 :             : !! write_dynq
     664                 :             : !!
     665                 :             : !! FUNCTION
     666                 :             : !!  Write a Quantum ESPRESSO dynamical-matrix file (dynq<iq>) for an irreducible q-point
     667                 :             : !!  AND all the q-points of its star, reproducing the layout of QE's write_dyn_on_file +
     668                 :             : !!  rotate_dvscf_star + dyndiag: a single header (cell, atoms), one "Dynamical Matrix in
     669                 :             : !!  cartesian axes" block per star member (representative q first), and a single
     670                 :             : !!  diagonalization block (frequencies and eigenvectors) for the representative q.
     671                 :             : !!
     672                 :             : !!  The star is generated from the ABINIT crystal symmetries (q' = symrec*q, deduplicated
     673                 :             : !!  modulo a reciprocal-lattice vector), and the dynamical matrix at each star member is
     674                 :             : !!  evaluated directly with ifc%fourq (equivalent to rotating D(q) by symmetry, since
     675                 :             : !!  D(Sq) = sum_R Phi(R) exp(i Sq.R); the gauge is irrelevant as D is gauge-invariant).
     676                 :             : !!  The Cartesian dynamical matrix is rebuilt as
     677                 :             : !!    phi(ka,k'b) = sqrt(M_k M_k') * sum_nu z(ka,nu) * w2(nu) * conjg(z(k'b,nu))
     678                 :             : !!  with z the orthonormal eigenvectors, w2 = signed omega^2 in Ry^2 and M the QE
     679                 :             : !!  Rydberg atomic masses (amu * amu_emass/2). This matches QE's convention.
     680                 :             : !!
     681                 :             : !! INPUTS
     682                 :             : !!  cryst<crystal_t>=crystal structure.
     683                 :             : !!  ifc<ifc_type>=interatomic force constants (for Fourier interpolation at q).
     684                 :             : !!  qpt_red(3)=q-point in reduced (crystal) coordinates.
     685                 :             : !!  alat=lattice parameter in Bohr (celldm(1)).
     686                 :             : !!  atm(ntypat)=atomic symbols.
     687                 :             : !!  fname=name of the output file.
     688                 :             : !!
     689                 :             : !! SOURCE
     690                 :             : 
     691                 :           0 : subroutine write_dynq(cryst, ifc, qpt_red, alat, atm, fname)
     692                 :             : 
     693                 :             : !Arguments ------------------------------------
     694                 :             :  class(crystal_t),intent(in) :: cryst
     695                 :             :  class(ifc_type),intent(in) :: ifc
     696                 :             :  real(dp),intent(in) :: qpt_red(3), alat
     697                 :             :  character(len=3),intent(in) :: atm(cryst%ntypat)
     698                 :             :  character(len=*),intent(in) :: fname
     699                 :             : 
     700                 :             : !Local variables-------------------------------
     701                 :             : !scalars
     702                 :             :  integer :: natom, nmodes, ntypat, unt, na, nb, icar, jcar, nu, it, isym, iqs, nq_star
     703                 :             :  real(dp),parameter :: Ha2Ry = two, accep = 1.0e-5_dp
     704                 :             :  real(dp) :: znorm, freq_cm, freq_thz
     705                 :             :  logical :: found
     706                 :             :  complex(dp) :: zi, zj, cs
     707                 :             :  character(len=500) :: msg
     708                 :             : !arrays
     709                 :             :  real(dp) :: at(3,3), bg(3,3), celldm(6), aq(3), raq(3), dq(3)
     710                 :           0 :  real(dp),allocatable :: phfrq(:), displ_cart(:,:,:,:), eigvec(:,:,:,:), w2(:), amass_qe(:), tau(:,:)
     711                 :           0 :  real(dp),allocatable :: saq(:,:), sxq(:,:), phfrq_rep(:), eigvec_rep(:,:,:,:)
     712                 :           0 :  complex(dp),allocatable :: phi(:,:,:,:)
     713                 :             : !----------------------------------------------------------------------
     714                 :             : 
     715                 :           0 :  natom = cryst%natom; nmodes = 3 * natom; ntypat = cryst%ntypat
     716                 :             : 
     717   [ #  #  #  #  :           0 :  ABI_MALLOC(phfrq, (nmodes))
          #  #  #  #  #  
                #  #  # ]
     718   [ #  #  #  #  :           0 :  ABI_MALLOC(displ_cart, (2, 3, natom, nmodes))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     719   [ #  #  #  #  :           0 :  ABI_MALLOC(eigvec, (2, 3, natom, nmodes))
          #  #  #  #  #  
                #  #  # ]
     720   [ #  #  #  #  :           0 :  ABI_MALLOC(w2, (nmodes))
             #  #  #  # ]
     721   [ #  #  #  #  :           0 :  ABI_MALLOC(amass_qe, (ntypat))
          #  #  #  #  #  
                #  #  # ]
     722   [ #  #  #  #  :           0 :  ABI_MALLOC(tau, (3, natom))
          #  #  #  #  #  
                #  #  # ]
     723   [ #  #  #  #  :           0 :  ABI_MALLOC(phi, (3, 3, natom, natom))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     724   [ #  #  #  #  :           0 :  ABI_MALLOC(saq, (3, cryst%nsym))
          #  #  #  #  #  
                #  #  # ]
     725   [ #  #  #  #  :           0 :  ABI_MALLOC(sxq, (3, cryst%nsym))
             #  #  #  # ]
     726   [ #  #  #  #  :           0 :  ABI_MALLOC(phfrq_rep, (nmodes))
             #  #  #  # ]
     727   [ #  #  #  #  :           0 :  ABI_MALLOC(eigvec_rep, (2, 3, natom, nmodes))
          #  #  #  #  #  
                #  #  # ]
     728                 :             : 
     729                 :             :  ! QE masses in Rydberg atomic units (amu * amu_ry, amu_ry = amu_emass/2).
     730         [ #  # ]:           0 :  do it=1,ntypat
     731                 :           0 :    amass_qe(it) = cryst%amu(it) * amu_emass * half
     732                 :             :  end do
     733                 :             : 
     734                 :             :  ! Cartesian cell quantities (alat / tpiba units).
     735         [ #  # ]:           0 :  do nu=1,3
     736         [ #  # ]:           0 :    at(:,nu) = cryst%rprimd(:,nu) / alat
     737         [ #  # ]:           0 :    bg(:,nu) = cryst%gprimd(:,nu) * alat
     738                 :             :  end do
     739         [ #  # ]:           0 :  do na=1,natom
     740   [ #  #  #  #  :           0 :    tau(:,na) = matmul(cryst%rprimd, cryst%xred(:,na)) / alat
          #  #  #  #  #  
                      # ]
     741                 :             :  end do
     742                 :           0 :  celldm = zero; celldm(1) = alat
     743                 :             : 
     744                 :             :  ! Build the star of qpt_red from the crystal symmetries (q' = symrec*q, deduplicated
     745                 :             :  ! modulo a reciprocal-lattice vector). The representative q is stored first (member 1).
     746                 :           0 :  aq(:) = qpt_red(:)
     747         [ #  # ]:           0 :  nq_star = 1; saq(:,1) = aq(:)
     748         [ #  # ]:           0 :  do isym=1,cryst%nsym
     749   [ #  #  #  #  :           0 :    raq = matmul(real(cryst%symrec(:,:,isym), dp), aq)
          #  #  #  #  #  
                      # ]
     750                 :           0 :    found = .False.
     751         [ #  # ]:           0 :    do iqs=1,nq_star
     752         [ #  # ]:           0 :      dq = raq - saq(:,iqs)
     753   [ #  #  #  #  :           0 :      if (all(abs(dq - nint(dq)) < accep)) then
                   #  # ]
     754                 :             :        found = .True.; exit
     755                 :             :      end if
     756                 :             :          end do
     757         [ #  # ]:           0 :    if (.not. found) then
     758         [ #  # ]:           0 :      nq_star = nq_star + 1; saq(:,nq_star) = raq(:)
     759                 :             :    end if
     760                 :             :        end do
     761         [ #  # ]:           0 :  do iqs=1,nq_star
     762   [ #  #  #  #  :           0 :    sxq(:,iqs) = matmul(bg, saq(:,iqs))   ! Cartesian (2pi/alat) coordinates
                   #  # ]
     763                 :             :  end do
     764                 :             : 
     765         [ #  # ]:           0 :  if (open_file(fname, msg, newunit=unt, form="formatted", status="unknown", action="write") /= 0) then
     766                 :           0 :    ABI_ERROR(msg)
     767                 :             :  end if
     768                 :             : 
     769                 :             :  ! ---- Header (written once) ----
     770                 :           0 :  write(unt, '(a)') "Dynamical matrix file"
     771                 :           0 :  write(unt, '(a)') "Converted from ABINIT GSTORE"
     772                 :             :  ! ntyp, nat, ibrav=0 (free lattice) followed by celldm; with ibrav=0 the basis vectors follow.
     773                 :           0 :  write(unt, '(i3,i5,i4,6f11.7)') ntypat, natom, 0, (celldm(it), it=1,6)
     774                 :           0 :  write(unt, '(a)') "Basis vectors"
     775         [ #  # ]:           0 :  do nu=1,3
     776                 :           0 :    write(unt, '(2x,3f15.9)') at(1,nu), at(2,nu), at(3,nu)
     777                 :             :  end do
     778         [ #  # ]:           0 :  do it=1,ntypat
     779                 :           0 :    write(unt, *) it, " '"//atm(it)//"' ", amass_qe(it)
     780                 :             :  end do
     781         [ #  # ]:           0 :  do na=1,natom
     782                 :           0 :    write(unt, '(2i5,3f18.10)') na, cryst%typat(na), tau(1,na), tau(2,na), tau(3,na)
     783                 :             :  end do
     784                 :             : 
     785                 :             :  ! ---- One dynamical-matrix block per q-point of the star ----
     786         [ #  # ]:           0 :  do iqs=1,nq_star
     787                 :             :    ! Frequencies, displacements and orthonormal eigenvectors at this star member.
     788                 :           0 :    call ifc%fourq(cryst, saq(:,iqs), phfrq, displ_cart, out_eigvec=eigvec)
     789         [ #  # ]:           0 :    if (iqs == 1) then
     790   [ #  #  #  #  :           0 :      phfrq_rep = phfrq; eigvec_rep = eigvec   ! keep the representative for the diag block
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     791                 :             :    end if
     792                 :             : 
     793                 :             :    ! Signed squared phonon frequencies in Ry^2.
     794         [ #  # ]:           0 :    do nu=1,nmodes
     795                 :           0 :      w2(nu) = phfrq(nu) * abs(phfrq(nu)) * Ha2Ry ** 2
     796                 :             :    end do
     797                 :             : 
     798                 :             :    ! Dynamical matrix in Cartesian axes (QE convention, see header).
     799         [ #  # ]:           0 :    do nb=1,natom
     800         [ #  # ]:           0 :      do na=1,natom
     801         [ #  # ]:           0 :        do jcar=1,3
     802         [ #  # ]:           0 :          do icar=1,3
     803                 :           0 :            cs = czero
     804         [ #  # ]:           0 :            do nu=1,nmodes
     805                 :           0 :              zi = cmplx(eigvec(1,icar,na,nu), eigvec(2,icar,na,nu), kind=dp)
     806                 :           0 :              zj = cmplx(eigvec(1,jcar,nb,nu), eigvec(2,jcar,nb,nu), kind=dp)
     807                 :           0 :              cs = cs + zi * w2(nu) * conjg(zj)
     808                 :             :            end do
     809                 :           0 :            phi(icar,jcar,na,nb) = sqrt(amass_qe(cryst%typat(na)) * amass_qe(cryst%typat(nb))) * cs
     810                 :             :          end do
     811                 :             :        end do
     812                 :             :      end do
     813                 :             :    end do
     814                 :             : 
     815                 :           0 :  write(unt, '(/,5x,a)') "Dynamical  Matrix in cartesian axes"
     816                 :           0 :    write(unt, '(/,5x,a,3f14.9,a,/)') "q = ( ", sxq(1,iqs), sxq(2,iqs), sxq(3,iqs), " ) "
     817         [ #  # ]:           0 :    do na=1,natom
     818         [ #  # ]:           0 :    do nb=1,natom
     819                 :           0 :      write(unt, '(2i5)') na, nb
     820         [ #  # ]:           0 :      do icar=1,3
     821                 :           0 :        write(unt, '(3(2f12.8,2x))') (phi(icar,jcar,na,nb), jcar=1,3)
     822                 :             :      end do
     823                 :             :    end do
     824                 :             :  end do
     825                 :             :  end do ! iqs
     826                 :             : 
     827                 :             :  ! ---- Diagonalization block (once, for the representative q = member 1) ----
     828                 :           0 :  write(unt, '(/,5x,a)') "Diagonalizing the dynamical matrix"
     829                 :           0 :  write(unt, '(/,5x,a,3f14.9,a,/)') "q = ( ", sxq(1,1), sxq(2,1), sxq(3,1), " ) "
     830                 :           0 :  write(unt, '(1x,74("*"))')
     831         [ #  # ]:           0 :  do nu=1,nmodes
     832                 :           0 :    freq_cm = phfrq_rep(nu) * Ha_cmm1
     833                 :           0 :    freq_thz = phfrq_rep(nu) * Ha_THz
     834                 :           0 :    write(unt, '(5x,a,i5,a,f15.6,a,f15.6,a)') "freq (", nu, ") = ", freq_thz, " [THz] = ", freq_cm, " [cm-1]"
     835                 :           0 :    znorm = zero
     836         [ #  # ]:           0 :    do na=1,natom
     837         [ #  # ]:           0 :      do icar=1,3
     838                 :           0 :        znorm = znorm + eigvec_rep(1,icar,na,nu)**2 + eigvec_rep(2,icar,na,nu)**2
     839                 :             :      end do
     840                 :             :    end do
     841         [ #  # ]:           0 :    znorm = sqrt(znorm); if (znorm < tol12) znorm = one
     842         [ #  # ]:           0 :    do na=1,natom
     843                 :           0 :      write(unt, '(1x,a,3(f10.6,1x,f10.6,3x),a)') "( ", &
     844   [ #  #  #  # ]:           0 :        (eigvec_rep(1,icar,na,nu)/znorm, eigvec_rep(2,icar,na,nu)/znorm, icar=1,3), ")"
     845                 :             :    end do
     846                 :             :  end do
     847                 :           0 :  write(unt, '(1x,74("*"))')
     848                 :             : 
     849                 :           0 :  close(unt)
     850                 :             : 
     851         [ #  # ]:           0 :  ABI_FREE(phfrq)
     852         [ #  # ]:           0 :  ABI_FREE(displ_cart)
     853         [ #  # ]:           0 :  ABI_FREE(eigvec)
     854         [ #  # ]:           0 :  ABI_FREE(w2)
     855         [ #  # ]:           0 :  ABI_FREE(amass_qe)
     856         [ #  # ]:           0 :  ABI_FREE(tau)
     857         [ #  # ]:           0 :  ABI_FREE(phi)
     858         [ #  # ]:           0 :  ABI_FREE(saq)
     859         [ #  # ]:           0 :  ABI_FREE(sxq)
     860         [ #  # ]:           0 :  ABI_FREE(phfrq_rep)
     861         [ #  # ]:           0 :  ABI_FREE(eigvec_rep)
     862                 :             : 
     863                 :           0 : end subroutine write_dynq
     864                 :             : !!***
     865                 :             : 
     866                 :             : !----------------------------------------------------------------------
     867                 :             : 
     868                 :             : !!****f* m_gstore_converters/write_qe_symmetry
     869                 :             : !! NAME
     870                 :             : !! write_qe_symmetry
     871                 :             : !!
     872                 :             : !! FUNCTION
     873                 :             : !!  Append the symmetry-operations block and the star of q to an already open
     874                 :             : !!  elph.mat.q_* file, reproducing the layout written by Quantum ESPRESSO's
     875                 :             : !!  elphsum_wannier (PHonon/PH/elphon.f90).
     876                 :             : !!
     877                 :             : !!  The QE quantities are reconstructed from the ABINIT crystal object using the
     878                 :             : !!  following correspondence (see PW/src/symm_base.f90, PHonon/PH/obsolete.f90 and
     879                 :             : !!  LR_Modules/star_q.f90 in the bundled QE sources):
     880                 :             : !!
     881                 :             : !!    QE s(:,:,isym)   = cryst%symrec(:,:,isym)   (rotations on reduced reciprocal coords;
     882                 :             : !!                                                 s^T = symrel^-1 acts on reduced positions)
     883                 :             : !!    QE irt(isym,na)  = cryst%indsym(4,isym,na)  (atom na -> atom irt under symrel^-1)
     884                 :             : !!    QE at(:,j)       = cryst%rprimd(:,j) / alat (direct lattice, alat units)
     885                 :             : !!    QE bg(:,j)       = cryst%gprimd(:,j) * alat (reciprocal lattice, 2pi/alat units)
     886                 :             : !!    QE tau / xau     = cryst%xred               (reduced atomic positions)
     887                 :             : !!
     888                 :             : !!  invs, rtau and the star (nq, sxq, isq, imq) are then obtained by porting QE's
     889                 :             : !!  inverse_s, sgam_ph and star_q. The symmetry operations are written in the native
     890                 :             : !!  ABINIT order (1..nsym); only the order differs from QE (which sorts the small
     891                 :             : !!  group of q first), the set and the per-operation data are equivalent.
     892                 :             : !!
     893                 :             : !! INPUTS
     894                 :             : !!  cryst<crystal_t>=crystal structure (with symmetries).
     895                 :             : !!  qpt(3)=q-point in reduced (crystal) coordinates.
     896                 :             : !!  alat=lattice parameter in Bohr (celldm(1)).
     897                 :             : !!  unt=Fortran unit of the (open) unformatted file.
     898                 :             : !!  ascii_write=if .True. also mirror the records in the formatted file unt_ascii.
     899                 :             : !!  unt_ascii=Fortran unit of the (open) formatted file (used only if ascii_write).
     900                 :             : !!
     901                 :             : !! SOURCE
     902                 :             : 
     903                 :           0 : subroutine write_qe_symmetry(cryst, qpt, alat, unt, ascii_write, unt_ascii)
     904                 :             : 
     905                 :             : !Arguments ------------------------------------
     906                 :             : !scalars
     907                 :             :  class(crystal_t),intent(in) :: cryst
     908                 :             :  integer,intent(in) :: unt, unt_ascii
     909                 :             :  logical,intent(in) :: ascii_write
     910                 :             :  real(dp),intent(in) :: alat
     911                 :             : !arrays
     912                 :             :  real(dp),intent(in) :: qpt(3)
     913                 :             : 
     914                 :             : !Local variables-------------------------------
     915                 :             : !scalars
     916                 :             :  integer :: nsym, natom, isym, jsym, ism1, i, j, k, na, nb, nq, imq, iq
     917                 :             :  logical :: found
     918                 :             :  real(dp),parameter :: accep = 1.0e-5_dp
     919                 :             : !arrays
     920                 :             :  integer :: ss(3,3)
     921                 :             :  integer,parameter :: identity(3,3) = reshape([1,0,0, 0,1,0, 0,0,1], [3,3])
     922                 :           0 :  integer,allocatable :: s(:,:,:), invs(:), irt(:,:), isq(:), nsq(:)
     923                 :             :  real(dp) :: at(3,3), bg(3,3), aq(3), raq(3), ft(3), dq(3)
     924                 :           0 :  real(dp),allocatable :: rtau(:,:,:), sxq(:,:), saq(:,:)
     925                 :             : !----------------------------------------------------------------------
     926                 :             : 
     927                 :           0 :  nsym = cryst%nsym; natom = cryst%natom
     928                 :             : 
     929   [ #  #  #  #  :           0 :  ABI_MALLOC(s, (3, 3, nsym))
          #  #  #  #  #  
                #  #  # ]
     930   [ #  #  #  #  :           0 :  ABI_MALLOC(invs, (nsym))
          #  #  #  #  #  
                #  #  # ]
     931   [ #  #  #  #  :           0 :  ABI_MALLOC(irt, (nsym, natom))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     932   [ #  #  #  #  :           0 :  ABI_MALLOC(isq, (nsym))
             #  #  #  # ]
     933   [ #  #  #  #  :           0 :  ABI_MALLOC(nsq, (nsym))
             #  #  #  # ]
     934   [ #  #  #  #  :           0 :  ABI_MALLOC(rtau, (3, nsym, natom))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     935   [ #  #  #  #  :           0 :  ABI_MALLOC(sxq, (3, nsym))
          #  #  #  #  #  
                #  #  # ]
     936   [ #  #  #  #  :           0 :  ABI_MALLOC(saq, (3, nsym))
             #  #  #  # ]
     937                 :             : 
     938                 :             :  ! Lattice vectors in QE units (at . bg^T = identity).
     939         [ #  # ]:           0 :  do j=1,3
     940         [ #  # ]:           0 :    at(:,j) = cryst%rprimd(:,j) / alat
     941         [ #  # ]:           0 :    bg(:,j) = cryst%gprimd(:,j) * alat
     942                 :             :  end do
     943                 :             : 
     944                 :             :  ! Rotations in crystal axis and atom mapping.
     945         [ #  # ]:           0 :  do isym=1,nsym
     946   [ #  #  #  # ]:           0 :    s(:,:,isym) = cryst%symrec(:,:,isym)
     947         [ #  # ]:           0 :    do na=1,natom
     948                 :           0 :      irt(isym, na) = cryst%indsym(4, isym, na)
     949                 :             :    end do
     950                 :             :  end do
     951                 :             : 
     952                 :             :  ! invs(isym): index of the inverse operation (ported from QE inverse_s).
     953         [ #  # ]:           0 :  do isym=1,nsym
     954                 :           0 :    found = .False.
     955         [ #  # ]:           0 :    do jsym=1,nsym
     956   [ #  #  #  #  :           0 :      ss = matmul(s(:,:,jsym), s(:,:,isym))
                   #  # ]
     957   [ #  #  #  #  :           0 :      if (all(ss == identity)) then
             #  #  #  # ]
     958                 :           0 :        invs(isym) = jsym; found = .True.; exit
     959                 :             :      end if
     960                 :             :    end do
     961                 :           0 :    ABI_CHECK(found, "write_qe_symmetry: symmetry operations do not form a group.")
     962                 :             :  end do
     963                 :             : 
     964                 :             :  ! rtau(:,isym,na) = S.tau_na - tau_nb in Cartesian coords (alat units), with nb = irt.
     965                 :             :  ! Ported from QE sgam_ph using xau = reduced atomic coordinates = cryst%xred.
     966   [ #  #  #  #  :           0 :  rtau = zero
                   #  # ]
     967         [ #  # ]:           0 :  do isym=1,nsym
     968         [ #  # ]:           0 :    do na=1,natom
     969                 :           0 :      nb = irt(isym, na)
     970         [ #  # ]:           0 :      do i=1,3
     971                 :             :        ft(i) = s(1,i,isym) * cryst%xred(1,na) + s(2,i,isym) * cryst%xred(2,na) &
     972                 :           0 :              + s(3,i,isym) * cryst%xred(3,na) - cryst%xred(i,nb)
     973                 :             :      end do
     974         [ #  # ]:           0 :      do i=1,3
     975                 :           0 :        rtau(i, isym, na) = at(i,1) * ft(1) + at(i,2) * ft(2) + at(i,3) * ft(3)
     976                 :             :      end do
     977                 :             :    end do
     978                 :             :  end do
     979                 :             : 
     980                 :             :  ! Star of q (ported from QE star_q). aq is q in reduced (crystal) coordinates.
     981                 :           0 :  aq(:) = qpt(:)
     982   [ #  #  #  #  :           0 :  nsq(:) = 0; isq(:) = 0; saq(:,:) = zero; sxq(:,:) = zero; nq = 0
          #  #  #  #  #  
                #  #  # ]
     983         [ #  # ]:           0 :  do isym=1,nsym
     984                 :           0 :    ism1 = invs(isym)
     985         [ #  # ]:           0 :    do i=1,3
     986                 :           0 :      raq(i) = s(i,1,ism1) * aq(1) + s(i,2,ism1) * aq(2) + s(i,3,ism1) * aq(3)
     987                 :             :    end do
     988         [ #  # ]:           0 :    do iq=1,nq
     989         [ #  # ]:           0 :      dq(:) = raq(:) - saq(:,iq)
     990   [ #  #  #  #  :           0 :      if (all(abs(dq - nint(dq)) < accep)) then
                   #  # ]
     991                 :           0 :        isq(isym) = iq; nsq(iq) = nsq(iq) + 1
     992                 :             :      end if
     993                 :             :    end do
     994         [ #  # ]:           0 :    if (isq(isym) == 0) then
     995         [ #  # ]:           0 :      nq = nq + 1; nsq(nq) = 1; isq(isym) = nq; saq(:,nq) = raq(:)
     996         [ #  # ]:           0 :      do i=1,3
     997                 :           0 :        sxq(i,nq) = bg(i,1) * saq(1,nq) + bg(i,2) * saq(2,nq) + bg(i,3) * saq(3,nq)
     998                 :             :      end do
     999                 :             :    end if
    1000                 :             :  end do
    1001                 :             : 
    1002                 :             :  ! imq: index of -q in the star (0 if absent).
    1003                 :           0 :  imq = 0
    1004         [ #  # ]:           0 :  do iq=1,nq
    1005         [ #  # ]:           0 :    dq(:) = -aq(:) - saq(:,iq)
    1006   [ #  #  #  #  :           0 :    if (all(abs(dq - nint(dq)) < accep)) imq = iq
                   #  # ]
    1007                 :             :  end do
    1008                 :             : 
    1009                 :             :  ! Sanity check on the star degeneracy (as in QE star_q).
    1010         [ #  # ]:           0 :  do iq=1,nq
    1011         [ #  # ]:           0 :    if (nsq(iq) * nq /= nsym) then
    1012                 :           0 :      ABI_WARNING(sjoin("write_qe_symmetry: unexpected star-of-q degeneracy for iq=", itoa(iq)))
    1013                 :             :    end if
    1014                 :             :  end do
    1015                 :             : 
    1016                 :             :  ! ---- Write the block in the QE elphsum_wannier order ----
    1017         [ #  # ]:           0 :  do j=1,3
    1018                 :           0 :    write(unt) (at(i,j), i=1,3)
    1019                 :             :  end do
    1020         [ #  # ]:           0 :  do j=1,3
    1021                 :           0 :    write(unt) (bg(i,j), i=1,3)
    1022                 :             :  end do
    1023                 :           0 :  write(unt) nsym, nq, imq
    1024         [ #  # ]:           0 :  do i=1,nsym
    1025                 :           0 :    write(unt) i, invs(i), isq(i)
    1026         [ #  # ]:           0 :    do j=1,3
    1027         [ #  # ]:           0 :      do k=1,3
    1028                 :           0 :        write(unt) k, j, s(k,j,i)
    1029                 :             :      end do
    1030                 :             :    end do
    1031         [ #  # ]:           0 :    do j=1,natom
    1032                 :           0 :      write(unt) j, irt(i,j)
    1033                 :             :    end do
    1034         [ #  # ]:           0 :    do j=1,3
    1035         [ #  # ]:           0 :      do k=1,natom
    1036                 :           0 :        write(unt) j, i, rtau(j,i,k)
    1037                 :             :      end do
    1038                 :             :    end do
    1039         [ #  # ]:           0 :    do j=1,3
    1040                 :           0 :      write(unt) j, sxq(j,i)
    1041                 :             :    end do
    1042                 :             :  end do
    1043                 :             : 
    1044                 :             :  ! ---- Optional human-readable mirror ----
    1045         [ #  # ]:           0 :  if (ascii_write) then
    1046                 :           0 :    write(unt_ascii, '(a)') "# Symmetry: direct lattice vectors at(:,j) (alat units)"
    1047         [ #  # ]:           0 :    do j=1,3
    1048                 :           0 :      write(unt_ascii, '(3es24.15)') (at(i,j), i=1,3)
    1049                 :             :    end do
    1050                 :           0 :    write(unt_ascii, '(a)') "# Symmetry: reciprocal lattice vectors bg(:,j) (2pi/alat units)"
    1051         [ #  # ]:           0 :    do j=1,3
    1052                 :           0 :      write(unt_ascii, '(3es24.15)') (bg(i,j), i=1,3)
    1053                 :             :    end do
    1054                 :           0 :    write(unt_ascii, '(a)') "# Symmetry: nsym, nq, imq"
    1055                 :           0 :    write(unt_ascii, '(3i8)') nsym, nq, imq
    1056         [ #  # ]:           0 :    do i=1,nsym
    1057                 :           0 :      write(unt_ascii, '(a,3i6)') "# isym, invs, isq: ", i, invs(i), isq(i)
    1058                 :           0 :      write(unt_ascii, '(a)') "#   rotation s(row k, col j)"
    1059         [ #  # ]:           0 :      do j=1,3
    1060         [ #  # ]:           0 :        do k=1,3
    1061                 :           0 :          write(unt_ascii, '(3i6)') k, j, s(k,j,i)
    1062                 :             :        end do
    1063                 :             :      end do
    1064                 :           0 :      write(unt_ascii, '(a)') "#   irt(atom)"
    1065         [ #  # ]:           0 :      do j=1,natom
    1066                 :           0 :        write(unt_ascii, '(2i6)') j, irt(i,j)
    1067                 :             :      end do
    1068                 :           0 :      write(unt_ascii, '(a)') "#   rtau(coord, isym, atom) (alat units)"
    1069         [ #  # ]:           0 :      do j=1,3
    1070         [ #  # ]:           0 :        do k=1,natom
    1071                 :           0 :          write(unt_ascii, '(2i6,es24.15)') j, i, rtau(j,i,k)
    1072                 :             :        end do
    1073                 :             :      end do
    1074                 :           0 :      write(unt_ascii, '(a)') "#   sxq(coord) (2pi/alat units)"
    1075         [ #  # ]:           0 :      do j=1,3
    1076                 :           0 :        write(unt_ascii, '(i6,es24.15)') j, sxq(j,i)
    1077                 :             :      end do
    1078                 :             :    end do
    1079                 :             :  end if
    1080                 :             : 
    1081         [ #  # ]:           0 :  ABI_FREE(s)
    1082         [ #  # ]:           0 :  ABI_FREE(invs)
    1083         [ #  # ]:           0 :  ABI_FREE(irt)
    1084         [ #  # ]:           0 :  ABI_FREE(isq)
    1085         [ #  # ]:           0 :  ABI_FREE(nsq)
    1086         [ #  # ]:           0 :  ABI_FREE(rtau)
    1087         [ #  # ]:           0 :  ABI_FREE(sxq)
    1088         [ #  # ]:           0 :  ABI_FREE(saq)
    1089                 :             : 
    1090                 :           0 : end subroutine write_qe_symmetry
    1091                 :             : !!***
    1092                 :             : 
    1093                 :             : !----------------------------------------------------------------------
    1094                 :             : 
    1095                 :             : ! Helper function copied from epic/src/io_matelem.F90
    1096                 :           0 : subroutine define_band_string(index, string, lstr)
    1097                 :             :   integer,intent(in) :: index
    1098                 :             :   integer,intent(out) :: lstr
    1099                 :             :   character(len=3),intent(out) :: string
    1100                 :             : 
    1101                 :             : ! here put a check on the string length
    1102                 :             : 
    1103                 :           0 :   string=' '
    1104         [ #  # ]:           0 :   if(index < 10) then
    1105                 :           0 :      WRITE( string(1:1), '(I1)' ) index
    1106                 :           0 :      lstr=1
    1107         [ #  # ]:           0 :   elseif(index < 100) then
    1108                 :           0 :      WRITE( string(1:2), '(I2)' ) index
    1109                 :           0 :      lstr=2
    1110         [ #  # ]:           0 :   elseif(index < 1000) then
    1111                 :           0 :      WRITE( string(1:3), '(I3)' ) index
    1112                 :           0 :      lstr=3
    1113                 :             :   endif
    1114                 :             : 
    1115                 :           0 :   string=trim(adjustl(string))
    1116                 :           0 : end subroutine define_band_string
    1117                 :             : 
    1118                 :           0 : end module m_gstore_converters
        

Generated by: LCOV version 2.3-1