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-09-20 18:56:22 Functions: 0.0 % 6 0

            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