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
|