Line data Source code
1 : !!****m* ABINIT/m_eprenorms
2 : !! NAME
3 : !! m_eprenorms
4 : !!
5 : !! FUNCTION
6 : !! This module contains datatypes to compute the renormalization of electronic states due to
7 : !! eph coupling and temperature effects
8 : !!
9 : !! NOTES
10 : !! This code is still under development and the API will change in the next versions.
11 : !! Contact gmatteo
12 : !!
13 : !! COPYRIGHT
14 : !! Copyright (C) 2001-2026 ABINIT group (YG)
15 : !! This file is distributed under the terms of the
16 : !! GNU General Public License, see ~abinit/COPYING
17 : !! or http://www.gnu.org/copyleft/gpl.txt .
18 : !!
19 : !! SOURCE
20 :
21 : #if defined HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "abi_common.h"
26 :
27 : module m_eprenorms
28 :
29 : use defs_basis
30 : use m_abicore
31 : use m_errors
32 : use m_xmpi
33 : use netcdf
34 : use m_nctk
35 : use m_ebands
36 :
37 : use m_crystal, only : crystal_t
38 : use m_kpts, only : listkk
39 :
40 : implicit none
41 :
42 : private
43 : !!***
44 :
45 : !!****t* m_eprenorms/eprenorms_t
46 : !! NAME
47 : !! eprenorms_t
48 : !!
49 : !! FUNCTION
50 : !! Datatype gathering data for electron-phonon renormalization of the band structure
51 : !!
52 : !! SOURCE
53 :
54 : type,public :: eprenorms_t
55 :
56 : !scalars
57 : integer :: nkpt
58 : ! Number of kpoints
59 :
60 : integer :: nsppol
61 : ! Number of spin channels
62 :
63 : integer :: mband
64 : ! Maximum number of bands
65 :
66 : integer :: ntemp
67 : ! Number of temperatures
68 :
69 : !arrays
70 : real(dp), allocatable :: kpts(:,:)
71 : ! kpt(3,nkpt)
72 : ! Kpoints
73 :
74 : real(dp), allocatable :: temps(:)
75 : ! temps(ntemp)
76 : ! Temperatures
77 :
78 : real(dp), allocatable :: eigens(:,:,:)
79 : ! eigens(mband,nkpt,nsppol)
80 : ! Kohn-Sham eigenvalues
81 :
82 : real(dp), allocatable :: occs(:,:,:)
83 : ! occ(mband,nkpt,nsppol)
84 : ! Occupation numbers
85 :
86 : real(dp), allocatable :: renorms(:,:,:,:,:)
87 : ! renorms(2,mband,nkpt,nsppol,ntemp)
88 : ! Renormalization of the eigenvalues for each temperature
89 :
90 : real(dp), allocatable :: linewidth(:,:,:,:,:)
91 : ! linewidth(2,mband,nkpt,nsppol,ntemp)
92 : ! Electron-phonon induced linewidth of the eigens
93 :
94 : end type eprenorms_t
95 :
96 : public :: eprenorms_init
97 : public :: eprenorms_free
98 : public :: eprenorms_from_epnc
99 : public :: eprenorms_bcast
100 :
101 : public :: renorm_bst
102 : !!***
103 :
104 : CONTAINS !============================================================================
105 : !!***
106 :
107 : !!****f* m_eprenorms/eprenorms_init
108 : !! NAME
109 : !! eprenorms_init
110 : !!
111 : !! FUNCTION
112 : !! Initializes an eprenorms_t datatype
113 : !!
114 : !! INPUTS
115 : !!
116 : !! OUTPUT
117 : !! Epren<eprenorms_t>=Datatype gathering electron-phonon renormalizations
118 : !!
119 : !! SOURCE
120 :
121 3 : subroutine eprenorms_init(Epren,nkpt,nsppol,mband,ntemp)
122 :
123 : !Arugments -----------------------------------
124 : !scalars
125 : integer,intent(in) :: nkpt, nsppol, mband, ntemp
126 : type(eprenorms_t) :: Epren
127 : !arrays
128 :
129 : !*************************************************************************
130 :
131 : DBG_ENTER("COLL")
132 :
133 3 : Epren%nkpt = nkpt
134 3 : Epren%nsppol = nsppol
135 3 : Epren%mband = mband
136 3 : Epren%ntemp = ntemp
137 :
138 9 : ABI_MALLOC(Epren%temps,(Epren%ntemp))
139 9 : ABI_MALLOC(Epren%kpts,(3,Epren%nkpt))
140 15 : ABI_MALLOC(Epren%eigens,(Epren%mband,Epren%nkpt,Epren%nsppol))
141 12 : ABI_MALLOC(Epren%occs,(Epren%mband,Epren%nkpt,Epren%nsppol))
142 18 : ABI_MALLOC(Epren%renorms,(2,Epren%mband,Epren%nkpt,Epren%nsppol,Epren%ntemp))
143 15 : ABI_MALLOC(Epren%linewidth,(2,Epren%mband,Epren%nkpt,Epren%nsppol,Epren%ntemp))
144 :
145 : DBG_EXIT("COLL")
146 :
147 3 : end subroutine eprenorms_init
148 : !!***
149 :
150 : !---------------------------------------------------------------------
151 :
152 : !!****f* m_eprenorms/eprenorms_free
153 : !! NAME
154 : !! eprenorms_free
155 : !!
156 : !! FUNCTION
157 : !! Deallocate all memory associated with eprenorms
158 : !!
159 : !! INPUTS
160 : !! Epren<eprenorms_t>=The datatype to be freed
161 : !!
162 : !! SOURCE
163 :
164 30 : subroutine eprenorms_free(Epren)
165 :
166 : !Arguments -----------------------------------
167 : !scalars
168 : type(eprenorms_t),intent(inout) :: Epren
169 :
170 : !*********************************************************************
171 :
172 30 : ABI_SFREE(Epren%temps)
173 30 : ABI_SFREE(Epren%kpts)
174 30 : ABI_SFREE(Epren%eigens)
175 30 : ABI_SFREE(Epren%occs)
176 30 : ABI_SFREE(Epren%renorms)
177 30 : ABI_SFREE(Epren%linewidth)
178 :
179 30 : end subroutine eprenorms_free
180 : !!***
181 :
182 : !---------------------------------------------------------------------
183 :
184 : !!****f* m_eprenorms/eprenorms_from_epnc
185 : !! NAME
186 : !! eprenorms_from_epnc
187 : !!
188 : !! FUNCTION
189 : !! Allocates and initializes the datatype from a _EP.nc file
190 : !!
191 : !! INPUTS
192 : !! filename = name of the file to be read
193 : !!
194 : !! SIDE EFFECTS
195 : !! Epren<eprenorms_t> = fields are initialized and filled with data from filename
196 : !!
197 : !! SOURCE
198 :
199 3 : subroutine eprenorms_from_epnc(Epren,filename)
200 :
201 : !Arguments -----------------------------------
202 : !scalars
203 : character(len=fnlen),intent(in) :: filename
204 : type(eprenorms_t),intent(inout) :: Epren
205 :
206 : !Local variables------------------------------
207 : integer :: nkpt, mband, nsppol, ntemp
208 : integer :: ncid
209 : ! ************************************************************************
210 :
211 3 : NCF_CHECK(nctk_open_read(ncid, filename, xmpi_comm_self))
212 3 : NCF_CHECK(nctk_set_datamode(ncid))
213 :
214 3 : NCF_CHECK(nctk_get_dim(ncid, "number_of_kpoints", nkpt))
215 3 : NCF_CHECK(nctk_get_dim(ncid, "number_of_spins",nsppol))
216 3 : NCF_CHECK(nctk_get_dim(ncid, "max_number_of_states",mband))
217 3 : NCF_CHECK(nctk_get_dim(ncid, "number_of_temperature",ntemp))
218 :
219 3 : call eprenorms_init(Epren, nkpt, nsppol, mband, ntemp)
220 :
221 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"reduced_coordinates_of_kpoints"), Epren%kpts))
222 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"temperature"), Epren%temps))
223 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"eigenvalues"), Epren%eigens))
224 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"occupations"), Epren%occs))
225 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"zero_point_motion"), Epren%renorms))
226 : ! TODO: This should be changed. What is stored is a linewidth, not a lifetime,
227 : ! we postone the change so as to not break compatibility
228 3 : NCF_CHECK(nf90_get_var(ncid, nctk_idname(ncid,"lifetime"), Epren%linewidth))
229 :
230 3 : end subroutine eprenorms_from_epnc
231 : !!***
232 :
233 : !---------------------------------------------------------------------
234 :
235 : !!****f* m_eprenorms/eprenorms_bcast
236 : !! NAME
237 : !! eprenorms_bcast
238 : !!
239 : !! FUNCTION
240 : !! MPI broadcast all the content of eprenorms_t
241 : !!
242 : !! INPUTS
243 : !! master = Rank of master
244 : !! comm = MPI communicator
245 : !!
246 : !! SIDE EFFECTS
247 : !! Epren<eprenorms_t> = Data broadcasted on every node from master
248 : !!
249 : !! SOURCE
250 :
251 3 : subroutine eprenorms_bcast(Epren,master,comm)
252 :
253 : !Arguments -----------------------------------
254 : !scalars
255 : integer,intent(in) :: master, comm
256 : type(eprenorms_t),intent(inout) :: Epren
257 :
258 : !Local variables------------------------------
259 : !scalars
260 : integer :: ierr
261 :
262 : ! ************************************************************************
263 :
264 3 : if (xmpi_comm_size(comm) == 1) return
265 :
266 0 : call xmpi_bcast(Epren%nkpt, master, comm, ierr)
267 0 : call xmpi_bcast(Epren%nsppol, master, comm, ierr)
268 0 : call xmpi_bcast(Epren%mband, master, comm, ierr)
269 0 : call xmpi_bcast(Epren%ntemp, master, comm, ierr)
270 :
271 0 : if (xmpi_comm_rank(comm) /= master) then
272 0 : call eprenorms_init(Epren, Epren%nkpt, Epren%nsppol, Epren%mband, Epren%ntemp)
273 : end if
274 :
275 0 : call xmpi_bcast(Epren%kpts, master, comm, ierr)
276 0 : call xmpi_bcast(Epren%temps, master, comm, ierr)
277 0 : call xmpi_bcast(Epren%eigens, master, comm, ierr)
278 0 : call xmpi_bcast(Epren%occs, master, comm, ierr)
279 0 : call xmpi_bcast(Epren%renorms, master, comm, ierr)
280 0 : call xmpi_bcast(Epren%linewidth, master, comm, ierr)
281 :
282 : end subroutine eprenorms_bcast
283 : !!***
284 :
285 : !---------------------------------------------------------------------
286 :
287 : !!****f* m_eprenorms/renorm_bst
288 : !! NAME
289 : !! renorm_bst
290 : !!
291 : !! FUNCTION
292 : !! Renormalize the band structure Bst from data contained Epren
293 : !!
294 : !! INPUTS
295 : !! Epren<eprenorms_t> = datatype containing the elphon renormalization
296 : !! itemp = index of the temperature you want to use
297 : !! do_lifetime = .true. if we want to use imaginary eigenvalues (lifetime field)
298 : !!
299 : !! SIDE EFFECTS
300 : !! Bst<bands_t> : eigens are changed according to epren
301 : !! linewidth is allocated and filled with data if do_linewidth
302 : !!
303 : !! SOURCE
304 :
305 50 : subroutine renorm_bst(Epren,Bst,Cryst,itemp,do_lifetime,do_check)
306 :
307 : !Arguments -----------------------------------
308 : !scalars
309 : integer :: itemp
310 : logical,intent(in) :: do_lifetime
311 : logical,optional,intent(in) :: do_check
312 : type(eprenorms_t),intent(in) :: Epren
313 : type(ebands_t),intent(inout) :: Bst
314 : type(crystal_t),intent(in) :: Cryst
315 :
316 : !Local variables------------------------------
317 : !scalars
318 : integer :: isppol,ikpt,comm
319 : integer :: nband1, nband_tmp
320 : integer :: timrev, sppoldbl
321 : integer :: ik_eph
322 : real(dp) :: dksqmax
323 : logical :: check
324 : !arrays
325 50 : integer,allocatable :: bs2eph(:,:)
326 :
327 : ! ************************************************************************
328 :
329 50 : ABI_CHECK(Bst%nsppol == Epren%nsppol, "Nsppol should be the same")
330 :
331 50 : comm = xmpi_comm_self
332 :
333 50 : if(do_lifetime) then
334 250 : ABI_MALLOC(Bst%linewidth,(1,Bst%mband,Bst%nkpt,Bst%nsppol))
335 : end if
336 :
337 50 : check = .TRUE.
338 50 : if(present(do_check)) then
339 50 : check = do_check
340 : end if
341 :
342 50 : sppoldbl = 1 !; if (any(Cryst%symafm == -1) .and. Epren%nsppol == 1) nsppoldbl=2
343 150 : ABI_MALLOC(bs2eph, (BSt%nkpt*sppoldbl, 6))
344 50 : timrev = 1
345 : call listkk(dksqmax, Cryst%gmet, bs2eph, Epren%kpts, BSt%kptns, Epren%nkpt, Bst%nkpt, Cryst%nsym, &
346 50 : & sppoldbl, Cryst%symafm, Cryst%symrel, timrev, comm, use_symrec=.False.)
347 :
348 100 : do isppol=1,Bst%nsppol
349 300 : do ikpt=1,Bst%nkpt
350 200 : nband1 = Bst%nband(ikpt+(isppol-1)*Bst%nkpt)
351 200 : nband_tmp=MIN(nband1,Epren%mband)
352 :
353 200 : ik_eph = bs2eph(ikpt,1)
354 :
355 : !FIXME change check
356 200 : if (check) then
357 1420 : if (ANY(ABS(Bst%eig(1:MIN(10,nband_tmp),ikpt,isppol) - Epren%eigens(1:MIN(10,nband_tmp),ik_eph,isppol)) > tol3)) then
358 : !write(stdout,*) "eig : ",BSt%eig(1:MIN(10,nband_tmp),ikpt,isppol)
359 : !write(stdout,*) "eigens : ",Epren%eigens(1:MIN(10,nband_tmp),ikpt,isppol)
360 0 : ABI_ERROR("Error in eigenvalues, check the _EP.nc file with respect to your input file !")
361 : end if
362 1420 : if (ANY(ABS(Bst%occ(1:MIN(10,nband_tmp),ikpt,isppol) - Epren%occs(1:MIN(10,nband_tmp),ik_eph,isppol)) > tol3)) then
363 0 : ABI_ERROR("Error in occupations, check the _EP.nc file with respect to your input file !")
364 : end if
365 : end if
366 :
367 : ! Upgrade energies
368 2280 : Bst%eig(1:nband_tmp,ikpt,isppol) = BSt%eig(1:nband_tmp,ikpt,isppol) + Epren%renorms(1,1:nband_tmp,ik_eph,isppol,itemp)
369 :
370 250 : if (do_lifetime) then
371 2280 : Bst%linewidth(1,1:nband_tmp,ikpt,isppol) = Epren%linewidth(1,1:nband_tmp,ik_eph,isppol,itemp)
372 : end if
373 : end do
374 : end do
375 :
376 50 : ABI_FREE(bs2eph)
377 :
378 50 : end subroutine renorm_bst
379 : !!***
380 :
381 : !---------------------------------------------------------------------
382 :
383 0 : end module m_eprenorms
384 : !!***
|