Line data Source code
1 : !!****m* ABINIT/m_spectra
2 : !! NAME
3 : !! m_spectra
4 : !!
5 : !! FUNCTION
6 : !! This module contains the definition of the specta_type data type
7 : !! used to store results related to optical spectra with or without
8 : !! nonlocal field effects as well as the electron energy loss function
9 : !! for a given q. These quantities are obtained from the dielectric
10 : !! matrix as calculated in the GW part of ABINIT (screening.F90)
11 : !!
12 : !! COPYRIGHT
13 : !! Copyright (C) 2008-2026 ABINIT group (MG)
14 : !! This file is distributed under the terms of the
15 : !! GNU General Public License, see ~abinit/COPYING
16 : !! or http://www.gnu.org/copyleft/gpl.txt .
17 : !!
18 : !! SOURCE
19 :
20 : #if defined HAVE_CONFIG_H
21 : #include "config.h"
22 : #endif
23 :
24 : #include "abi_common.h"
25 :
26 : MODULE m_spectra
27 :
28 : use defs_basis
29 : use m_errors
30 : use m_abicore
31 :
32 : use m_io_tools, only : open_file
33 : use m_fstrings, only : strcat
34 :
35 : implicit none
36 :
37 : private
38 : !!***
39 :
40 : !!****t* m_spectra/spectra_t
41 : !! NAME
42 : !! spectra_t
43 : !!
44 : !! FUNCTION
45 : !! Object used to store optical spectra with or without non-local field effects.
46 : !!
47 : !! SOURCE
48 :
49 : type,public :: spectra_t
50 :
51 : !scalars
52 : integer :: nomega
53 : ! number of frequencies
54 :
55 : integer :: nqpts
56 : ! number of q-points
57 :
58 : !arrays
59 : real(dp),allocatable :: omega(:)
60 : ! omega(nomega)
61 : ! Real frequency mesh for optical spectra.
62 :
63 : real(dp),allocatable :: qpts(:,:)
64 : ! qpts(3,nqpoints)
65 : ! The list of q-points used for the spectra
66 :
67 : real(dp),allocatable :: eelf(:,:)
68 : ! eelf(nomega,nqpoints)
69 : ! contains the Electron Energy Loss Function i.e. -\Im{ e^{-1}_{G1=0,G2=0}(q-->0,nomega)}
70 :
71 : complex(dp),allocatable :: emacro_lf(:,:)
72 : ! emacro_lf(nomega,nqpoints)
73 : ! contains 1/e^{-1}_{G1=0,G2=0}(q-->0,nomega) (with Local field effects)
74 :
75 : complex(dp),allocatable :: emacro_nlf(:,:)
76 : ! emacro_nlf(nomega,nqpoints)
77 : ! contains e_{G1=0,G2=0}(q-->0,nomega) (without Local field effects)
78 :
79 : contains
80 :
81 : procedure :: free => spectra_free
82 : ! Free memory.
83 :
84 : procedure :: write => spectra_write
85 : ! Write results on file.
86 :
87 : procedure :: repr => spectra_repr
88 : ! Return info on Macroscopic diel. constant in form of a string.
89 :
90 : end type spectra_t
91 : !!***
92 :
93 : public :: spectra_init ! Creation method.
94 :
95 : integer,public,parameter :: W_EM_LF = 1
96 : integer,public,parameter :: W_EM_NLF = 2
97 : integer,public,parameter :: W_EELF = 4
98 :
99 : CONTAINS !========================================================================================
100 : !!***
101 :
102 : !!****f* m_spectra/spectra_init
103 : !! NAME
104 : !! spectra_init
105 : !!
106 : !! FUNCTION
107 : !! Initialize the object.
108 : !!
109 : !! INPUTS
110 : !!
111 : !! OUTPUT
112 : !!
113 : !! SOURCE
114 :
115 950 : subroutine spectra_init(Spectra,nomega,omega,nqpts,qpts)
116 :
117 : !Arguments ------------------------------------
118 : !scalars
119 : integer,intent(in) :: nomega,nqpts
120 : !arrays
121 : real(dp),intent(in) :: omega(nomega),qpts(3,nqpts)
122 : type(spectra_t),intent(out) :: Spectra
123 :
124 : ! *********************************************************************
125 :
126 950 : Spectra%nomega = nomega
127 950 : Spectra%nqpts = nqpts
128 :
129 2850 : ABI_MALLOC(Spectra%qpts,(3,nqpts))
130 5700 : Spectra%qpts = qpts
131 :
132 2850 : ABI_MALLOC(Spectra%omega,(nomega))
133 4633 : Spectra%omega = omega
134 :
135 7483 : ABI_CALLOC(Spectra%emacro_lf,(nomega,nqpts))
136 6533 : ABI_CALLOC(Spectra%emacro_nlf,(nomega,nqpts))
137 7483 : ABI_CALLOC(Spectra%eelf,(nomega,nqpts))
138 :
139 950 : end subroutine spectra_init
140 : !!***
141 :
142 : !----------------------------------------------------------------------
143 :
144 : !!****f* m_spectra/spectra_free
145 : !! NAME
146 : !! spectra_free
147 : !!
148 : !! FUNCTION
149 : !! Deallocate all associated pointers defined in the structure.
150 : !!
151 : !! INPUTS
152 : !!
153 : !! OUTPUT
154 : !!
155 : !! SOURCE
156 :
157 950 : subroutine spectra_free(Spectra)
158 :
159 : !Arguments ------------------------------------
160 : class(spectra_t),intent(inout) :: spectra
161 :
162 : ! *********************************************************************
163 :
164 950 : ABI_SFREE(Spectra%omega)
165 950 : ABI_SFREE(Spectra%qpts)
166 950 : ABI_SFREE(Spectra%emacro_lf)
167 950 : ABI_SFREE(Spectra%emacro_nlf)
168 950 : ABI_SFREE(Spectra%eelf)
169 :
170 950 : end subroutine spectra_free
171 : !!***
172 :
173 : !----------------------------------------------------------------------
174 :
175 : !!****f* m_spectra/spectra_write
176 : !! NAME
177 : !! spectra_write
178 : !!
179 : !! FUNCTION
180 : !! Write the optical spectra stored in the object on an external formatted file.
181 : !!
182 : !! INPUTS
183 : !! Spectra=The Object containing the spectra
184 : !! write_bits=Positive integer defining the quantities to be written (bit representation is used)
185 : !! fname=Name of the file to be written.
186 : !!
187 : !! OUTPUT
188 : !!
189 : !! SOURCE
190 :
191 66 : subroutine spectra_write(Spectra,write_bits,fname)
192 :
193 : !Arguments ------------------------------------
194 : !scalars
195 : class(spectra_t),intent(in) :: Spectra
196 : integer,intent(in) :: write_bits
197 : character(len=*),intent(in) :: fname
198 :
199 : !Local variables-------------------------------
200 : !scalars
201 : integer :: unt,io,iqpt
202 : real(dp) :: mino,maxo
203 : character(len=100) :: fmt
204 : character(len=500) :: msg
205 :
206 : ! *********************************************************************
207 :
208 66 : if (write_bits<0) RETURN
209 :
210 : mino = MINVAL(Spectra%omega)
211 : maxo = MAXVAL(Spectra%omega)
212 :
213 66 : if (open_file(fname,msg,newunit=unt) /= 0) then
214 0 : ABI_ERROR(msg)
215 : end if
216 :
217 : !write(unt,'(a,i5,2(a,f9.1),a)')'# nomega : ',Spectra%nomega,' from ',mino*Ha_eV,' up to ',maxo*Ha_eV,' [eV] '
218 :
219 66 : if ( IAND(write_bits,W_EM_NLF ) == W_EM_NLF ) then
220 22 : write(unt,'(a)')'#'
221 22 : write(unt,'(a)')'# Macroscopic Dielectric Function without local fields'
222 22 : call dump_qlist()
223 22 : write(unt,'(a)')'# Omega [eV] Re epsilon_M IM eps_M '
224 22 : write(fmt,'(a,i3,a)') '(1x,f7.3,7x,',Spectra%nqpts,'(2(e12.4),2x))'
225 278 : do io=1,Spectra%nomega
226 534 : write(unt,fmt) Spectra%omega(io)*Ha_eV, ( Spectra%emacro_nlf(io,iqpt), iqpt=1,Spectra%nqpts )
227 : end do
228 : end if
229 : !
230 66 : if ( IAND(write_bits, W_EM_LF ) == W_EM_LF ) then
231 22 : write(unt,'(a)')'#'
232 22 : write(unt,'(a)')'# Macroscopic Dielectric Function with local fields included'
233 22 : call dump_qlist()
234 22 : write(unt,'(a)')'# Omega [eV] Re epsilon_M Im eps_M '
235 22 : write(fmt,'(a,i3,a)') '(1x,f7.3,7x,',Spectra%nqpts,'(2(e12.4),2x))'
236 278 : do io=1,Spectra%nomega
237 534 : write(unt,fmt) Spectra%omega(io)*Ha_eV, ( Spectra%emacro_lf(io,iqpt), iqpt=1,Spectra%nqpts )
238 : end do
239 : end if
240 : !
241 66 : if ( IAND(write_bits,W_EELF) == W_EELF) then
242 22 : write(unt,'(a)')'#'
243 22 : write(unt,'(a)')'# Electron Energy Loss Function -Im(1/epsilon_M)'
244 22 : call dump_qlist()
245 22 : write(unt,'(a)')'# Omega [eV] -Im(1/epsilon_M)'
246 22 : write(fmt,'(a,i3,a)') '(1x,f7.3,7x,',Spectra%nqpts,'(e12.4,2x))'
247 278 : do io=1,Spectra%nomega
248 534 : write(unt,fmt) Spectra%omega(io)*Ha_eV, ( Spectra%eelf(io,iqpt), iqpt=1,Spectra%nqpts ) ! -AIMAG(chi0(1,1,io))
249 : end do
250 : end if
251 :
252 66 : close(unt)
253 :
254 : CONTAINS
255 : !!***
256 :
257 : !!****f* m_spectra/dump_Qlist
258 : !! NAME
259 : !! dump_Qlist
260 : !!
261 : !! FUNCTION
262 : !! Helper function used to write the list of q-points used for the long-wavelength limit.
263 : !!
264 : !! INPUTS
265 : !! Spectra=The Object containing the spectra
266 : !!
267 : !! OUTPUT
268 : !! Only writing.
269 : !!
270 : !! SOURCE
271 :
272 66 : subroutine dump_Qlist()
273 :
274 : integer :: iqpt
275 66 : write(unt,'(a,i3)')'# Q-point list, No. ',Spectra%nqpts
276 132 : do iqpt=1,Spectra%nqpts
277 132 : write(unt,'(a,i3,a,3f9.6,a)')'# ',iqpt,') [',Spectra%qpts(:,iqpt),'] r.l.u. '
278 : end do
279 66 : end subroutine dump_Qlist
280 :
281 : end subroutine spectra_write
282 : !!***
283 :
284 : !----------------------------------------------------------------------
285 :
286 : !!****f* m_spectra/spectra_repr
287 : !! NAME
288 : !! spectra_repr
289 : !!
290 : !! FUNCTION
291 : !! Returns a string reporting info on the calculated dielectric constant.
292 : !!
293 : !! INPUTS
294 : !! Spectra=The Object containing the spectra
295 : !!
296 : !! OUTPUT
297 : !!
298 : !! SOURCE
299 :
300 123 : subroutine spectra_repr(Spectra,str)
301 :
302 : !Arguments ------------------------------------
303 : !scalars
304 : class(spectra_t),intent(in) :: Spectra
305 : character(len=*),intent(out) :: str
306 :
307 : !Local variables-------------------------------
308 : !scalars
309 : integer :: iqpt
310 : real(dp) :: epsilon0,epsilon0_nlf
311 : character(len=15), parameter :: format_f84 = '(1x,a, f8.4,a)'
312 : character(len=15), parameter :: format_es135 = '(1x,a,es13.5,a)'
313 : character(len=15) :: format_diel
314 : character(len=500) :: msg
315 :
316 : ! *********************************************************************
317 :
318 : !istatic = -1
319 : !do io = Spectra%nomega
320 : ! if (ABS(REAL(Spectra%omega(io)))<1.e-3.and.ABS(AIMAG(Spectra%omega(io)))<1.e-3) then
321 : ! istatic = io
322 : ! EXIT
323 : ! end if
324 : !end do
325 :
326 123 : str = ""
327 246 : do iqpt=1,Spectra%nqpts
328 123 : epsilon0 = REAL(Spectra%emacro_lf (1,iqpt))
329 123 : epsilon0_nlf= REAL(Spectra%emacro_nlf(1,iqpt))
330 123 : write(msg,'(a,3f9.6,a)')' For q-point: ',Spectra%qpts(:,iqpt),ch10
331 123 : format_diel=format_f84
332 123 : if(abs(epsilon0)>1000.0d0 .or. abs(epsilon0_nlf)>1000.0d0) format_diel=format_es135
333 123 : str = strcat(str,msg)
334 123 : write(msg,format_diel)' dielectric constant = ',epsilon0,ch10
335 123 : str = strcat(str,msg)
336 123 : write(msg,format_diel)' dielectric constant without local fields = ',epsilon0_nlf,ch10
337 246 : str = strcat(str,msg)
338 : end do
339 :
340 123 : end subroutine spectra_repr
341 :
342 : !----------------------------------------------------------------------
343 :
344 0 : END MODULE m_spectra
345 : !!***
|