Line data Source code
1 : !!****m* ABINIT/m_ppmodel
2 : !! NAME
3 : !! m_ppmodel
4 : !!
5 : !! FUNCTION
6 : !! Module containing the definition of the ppmodel_t used to deal with the plasmonpole technique.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2008-2026 ABINIT group (MG, GMR, VO, LR, RWG, RS)
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_ppmodel
23 :
24 : use defs_basis
25 : use m_errors
26 : use m_abicore
27 : use m_array
28 : use m_linalg_interfaces
29 : use m_distribfft
30 : use m_yaml
31 :
32 : use defs_abitypes, only : MPI_type
33 : use m_fstrings, only : sjoin, itoa, ktoa
34 : use m_hide_lapack, only : xhegv
35 : use m_gwdefs, only : GW_Q0_DEFAULT, czero_gw
36 : use m_crystal, only : crystal_t
37 : use m_bz_mesh, only : kmesh_t
38 : use m_gsphere, only : gsphere_t
39 : use m_vcoul, only : vcoul_t
40 : use m_qplusg, only : cmod_qpg
41 : use m_fft_mesh, only : g2ifft
42 : use m_fft, only : fourdp
43 : use m_mpinfo, only : destroy_mpi_enreg, initmpi_seq
44 : use m_pstat, only : pstat_proc
45 :
46 : implicit none
47 :
48 : private
49 : !!***
50 :
51 : integer,public,parameter :: PPM_NONE = 0
52 : integer,public,parameter :: PPM_GODBY_NEEDS = 1
53 : integer,public,parameter :: PPM_HYBERTSEN_LOUIE = 2
54 : integer,public,parameter :: PPM_LINDEN_HORSH = 3
55 : integer,public,parameter :: PPM_ENGEL_FARID = 4
56 :
57 : ! Flags giving the status of the plasmon-pole tables
58 : integer,public,parameter :: PPM_NOTAB = 0
59 : integer,public,parameter :: PPM_TAB_ALLOCATED = 1
60 : integer,public,parameter :: PPM_TAB_STORED = 2
61 :
62 : !----------------------------------------------------------------------
63 :
64 : !!****t* m_ppmodel/ppmodel_t
65 : !! NAME
66 : !! ppmodel_t
67 : !!
68 : !! FUNCTION
69 : !! This datatype gathers all the information on the Plasmonpole technique used in the calculations
70 : !!
71 : !! SOURCE
72 :
73 : type,public :: ppmodel_t
74 :
75 : integer :: dm2_botsq
76 : ! =npwc if ppmodel=1,2
77 : ! =1 if ppmodel=3,4
78 :
79 : integer :: dm_eig
80 : ! =0 if ppmodel=1,2,4
81 : ! =npwc if ppmodel=3
82 :
83 : integer :: dm2_otq
84 : ! =npwc if ppmodel=1,2
85 : ! =1 if ppmodel=3,4
86 :
87 : integer :: invalid_freq
88 : ! what to do when PPM frequencies are invalid.
89 :
90 : integer :: model
91 : ! The type of Plasmonpole model.
92 :
93 : integer :: mqmem
94 : ! =nqibz if in-core solution.
95 : ! =0 for out-of-core for which the last dimension in the ppm arrays has size 1.
96 :
97 : integer :: nqibz
98 : ! Number of q-points in the IBZ
99 :
100 : integer :: npwc
101 : ! Number of G vectors in $\tilde \epsilon $
102 :
103 : integer :: userho
104 : ! 1 if the ppmodel requires rho(G).
105 :
106 : integer :: iq_bz = 0
107 : ! The index of the q-point in the BZ that is referenced by the internal pointer.
108 : ! when we perform a symmetrization from the IBZ to the BZ.
109 :
110 : real(dp) :: drude_plsmf
111 : ! Drude plasma frequency
112 :
113 : real(dp) :: force_plsmf = zero
114 : ! Force plasma frequency to that set by ppmfreq (not used if set zero).
115 :
116 : ! arrays
117 : logical,allocatable :: keep_qibz(:)
118 : ! (nqibz)
119 : ! .TRUE. if the ppmodel tables for this q in the IBZ are kept in memory.
120 :
121 : integer,allocatable :: has_qibz(:)
122 : ! Flag defining the status of the tables for the different q. See the PPM_TAB flags.
123 :
124 : complex(gwp),allocatable :: bigomegatwsq_qbz_vals(:,:)
125 : ! (Points|Stores) the symmetrized plasmon pole parameters $\tilde\Omega^2_{G Gp}(q_bz)$.
126 :
127 : complex(gwp),allocatable :: omegatw_qbz_vals(:,:)
128 : ! (Points|Stores) the symmetrized plasmon pole parameters $\tilde\omega_{G Gp}(q_bz)$.
129 :
130 : complex(gwp),allocatable :: eigpot_qbz_vals(:,:)
131 : ! (Points|Stores) the eigvectors of the symmetrized inverse dielectric matrix.
132 :
133 : type(array2_gwpc_t),allocatable :: bigomegatwsq(:)
134 : ! (nqibz)%value(npwc,dm2_botsq)
135 : ! Plasmon pole parameters $\tilde\Omega^2_{G Gp}(q)$.
136 :
137 : type(array2_gwpc_t),allocatable :: omegatw(:)
138 : ! (nqibz)%value(npwc,dm2_otq)
139 : ! Plasmon pole parameters $\tilde\omega_{G Gp}(q)$.
140 :
141 : type(array2_gwpc_t),allocatable :: eigpot(:)
142 : ! (nqibz)%value(dm_eig,dm_eig)
143 : ! Eigvectors of the symmetrized inverse dielectric matrix.
144 :
145 : contains
146 :
147 : procedure :: get_qbz => ppm_get_qbz
148 : ! Symmetrize the ppm parameters in the BZ.
149 :
150 : procedure :: init => ppm_init
151 : ! Initialize dimensions and pointers
152 :
153 : procedure :: free => ppm_free
154 : ! Free dynamic memory.
155 :
156 : procedure :: setup => ppm_setup
157 : ! Main Driver
158 :
159 : procedure :: new_setup => ppm_new_setup
160 : ! New Main Driver
161 :
162 : procedure :: print => ppm_print
163 : ! Print info on object
164 :
165 : procedure :: calc_sigc => ppm_calc_sigc
166 : ! Matrix elements of the correlated self-energy with ppmodel.
167 :
168 : procedure :: rotate_iqbz => ppm_rotate_iqbz
169 :
170 : procedure :: malloc_iqibz => ppm_malloc_iqibz
171 :
172 : procedure :: table_free_iqibz => ppm_table_free_iqibz
173 :
174 : procedure :: get_eigenvalues => ppm_get_eigenvalues
175 :
176 : procedure :: getem1 => ppm_getem1
177 : ! Reconstruct e^{-1}(w) from ppm.
178 :
179 : procedure :: getem1_one_ggp => ppm_getem1_one_ggp
180 : ! Reconstruct e^{-1}(w) from ppm for one (G,G') pair
181 :
182 : end type ppmodel_t
183 :
184 : public :: cqratio
185 : !!***
186 :
187 : contains
188 : !!***
189 :
190 : !!****f* m_ppmodel/ppm_get_qbz
191 : !! NAME
192 : !! ppm_get_qbz
193 : !!
194 : !! FUNCTION
195 : !! Compute plasmon-pole matrix elements for q in the BZ from the symmetrical image in the IBZ
196 : !!
197 : !! INPUTS
198 : !! Gsph<gsphere_t>=data related to the G-sphere
199 : !! Qmesh<kmesh_t>=Info on the q-mesh
200 : !! iq_bz=Index of the q-point in the BZ where ppmodel parameters have to be symmetrized
201 : !!
202 : !! OUTPUT
203 : !! botsq
204 : !! otq
205 : !! eig (only if ppm%ppmodel==3)
206 : !!
207 : !! NOTES
208 : !! In the present implementation we are not considering a possible umklapp vector G0.
209 : !! In this case,indeed, the equation is different since we have to consider G-G0.
210 : !! There is however a check in sigma
211 : !!
212 : !! * Remember the symmetry properties of \tilde\espilon^{-1}
213 : !!
214 : !! If q_bz=Sq_ibz+G0:
215 : !!
216 : !! $\epsilon^{-1}_{SG1-G0,SG2-G0}(q_bz) = e^{+iS(G2-G1).\tau}\epsilon^{-1}_{G1,G2)}(q)
217 : !!
218 : !! If time-reversal symmetry can be used then:
219 : !!
220 : !! $\epsilon^{-1}_{G1,G2}(-q_bz) = e^{+i(G1-G2).\tau}\epsilon^{-1}_{-S^{-1}(G1+Go),-S^{-1}(G2+G0)}^*(q)
221 : !!
222 : !! * Note that eig is used only if ppm%model==3
223 : !!
224 : !! SOURCE
225 :
226 14818 : subroutine ppm_get_qbz(ppm, Gsph, Qmesh, iq_bz, botsq, otq, eig)
227 :
228 : !Arguments ------------------------------------
229 : !scalars
230 : class(ppmodel_t),target,intent(inout) :: ppm
231 : integer,intent(in) :: iq_bz
232 : type(gsphere_t),target,intent(in) :: Gsph
233 : type(kmesh_t),intent(in) :: Qmesh
234 : complex(gwp),allocatable,intent(out) :: botsq(:,:),otq(:,:),eig(:,:)
235 :
236 : !Local variables-------------------------------
237 : !scalars
238 : integer :: ii,jj,iq_ibz,itim_q,isym_q,iq_curr,isg1,isg2
239 : !arrays
240 14818 : integer, contiguous, pointer :: grottb(:)
241 14818 : complex(gwp),contiguous, pointer :: phsgt(:),bigomegatwsq(:,:),omegatw(:,:)
242 : ! *********************************************************************
243 :
244 : ! Save the index of the q-point for checking purpose.
245 14818 : ppm%iq_bz = iq_bz
246 :
247 59272 : ABI_MALLOC(botsq, (ppm%npwc, ppm%dm2_botsq))
248 59272 : ABI_MALLOC(otq, (ppm%npwc, ppm%dm2_otq))
249 59272 : ABI_MALLOC(eig, (ppm%dm_eig, ppm%dm_eig))
250 :
251 : ! Here there is a problem with the small q, still cannot use BZ methods
252 14818 : iq_ibz = Qmesh%tab(iq_bz); isym_q = Qmesh%tabo(iq_bz); itim_q = (3-Qmesh%tabi(iq_bz))/2
253 :
254 59272 : ABI_CHECK(all(abs(qmesh%umklp(:, iq_bz)) < tol6), "umklapp in get_qbz are not supported!")
255 :
256 : !call Qmesh%get_bz_item(iq_bz,qbz,iq_ibz,isym_q,itim_q,isirred=q_isirred)
257 14818 : iq_curr = iq_ibz; if (ppm%mqmem == 0) iq_curr = 1
258 :
259 14818 : grottb => Gsph%rottb (1:ppm%npwc, itim_q, isym_q)
260 14818 : phsgt => Gsph%phmSGt(1:ppm%npwc, isym_q)
261 14818 : bigomegatwsq => ppm%bigomegatwsq(iq_curr)%vals
262 14818 : omegatw => ppm%omegatw(iq_curr)%vals
263 :
264 : ! Symmetrize the PPM parameters
265 14818 : select case (ppm%model)
266 : case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
267 : ! Plasmon pole frequencies otq are invariant under symmetry
268 : !$omp parallel do private(isg1, isg2)
269 473958 : do jj=1,ppm%npwc
270 459332 : isg2 = grottb(jj)
271 21075832 : do ii=1,ppm%npwc
272 20601874 : isg1 = grottb(ii)
273 20601874 : botsq(isg1,isg2) = bigomegatwsq(ii,jj)*phsgt(ii)*CONJG(phsgt(jj))
274 21061206 : otq (isg1,isg2) = omegatw(ii,jj)
275 : end do
276 : end do
277 :
278 : case (PPM_LINDEN_HORSH)
279 : ! For notations see page 22 of Quasiparticle Calculations in solid (Aulbur et al)
280 : ! If q_bz = Sq_ibz + G0 then:
281 : !
282 : ! $\omega^2_{ii}(q_bz) = \omega^2_{ii}(q)$ (otq array)
283 : ! $\alpha_{ii}(q_bz) = \alpha_{ii}(q)$ (botq array
284 : ! $\Phi_{SG-G0}(q_bz) = \Phi_{G}(q) e^{-iSG.t}$ (eigenvectors of e^{-1}, eig array)
285 : !
286 2688 : do ii=1,ppm%npwc ! DM bands index
287 2592 : botsq(ii,1) = bigomegatwsq(ii,1)
288 2592 : otq (ii,1) = omegatw (ii,1)
289 72672 : do jj=1,ppm%npwc
290 72576 : eig(grottb(jj),ii) = ppm%eigpot(iq_curr)%vals(jj,ii) * phsgt(jj)
291 : end do
292 : end do
293 96 : if (itim_q==2) eig=CONJG(eig) ! Time-reversal
294 :
295 : case (PPM_ENGEL_FARID)
296 : ! For notations see page 23 of Quasiparticle Calculations in solid (Aulbur et al.)
297 : ! If q_bz = Sq_ibz + G0 then:
298 : !
299 : ! $\omega^2_{ii}(q_bz) = \omega^2_{ii}(q)$ (otq array)
300 : ! $y_{SG-G0}(q_bz) = y_{G}(q) e^{-iSG.t}$ (y=Lx)
301 : !
302 2688 : do ii=1,ppm%npwc ! DM bands index
303 2592 : otq(ii,1) = omegatw(ii,1)
304 72672 : do jj=1,ppm%npwc
305 72576 : botsq(grottb(jj),ii) = bigomegatwsq(jj,ii)*phsgt(jj)
306 : end do
307 : end do
308 :
309 : case default
310 14818 : ABI_BUG(sjoin('Wrong ppm%model:',itoa(ppm%model)))
311 : end select
312 :
313 : ! Take into account time-reversal symmetry.
314 14722 : if (itim_q == 2) then
315 : !$omp parallel workshare
316 809858 : botsq=CONJG(botsq)
317 : !$omp end parallel workshare
318 : end if
319 :
320 14818 : end subroutine ppm_get_qbz
321 : !!***
322 :
323 : !----------------------------------------------------------------------
324 :
325 : !!****f* m_ppmodel/ppm_free
326 : !! NAME
327 : !! ppm_free
328 : !!
329 : !! FUNCTION
330 : !! Deallocate all associated pointers defined in a variable of type ppmodel_t.
331 : !!
332 : !! SOURCE
333 :
334 233 : subroutine ppm_free(ppm)
335 :
336 : !Arguments ------------------------------------
337 : class(ppmodel_t),intent(inout) :: ppm
338 :
339 : !Local variables-------------------------------
340 : integer :: dim_q,iq_ibz
341 : ! *********************************************************************
342 :
343 233 : ABI_SFREE(ppm%bigomegatwsq_qbz_vals)
344 233 : ABI_SFREE(ppm%omegatw_qbz_vals)
345 233 : ABI_SFREE(ppm%eigpot_qbz_vals)
346 :
347 233 : dim_q = ppm%nqibz; if (ppm%mqmem==0) dim_q=1
348 :
349 233 : if (allocated(ppm%bigomegatwsq)) then
350 981 : do iq_ibz=1,dim_q
351 981 : call ppm%bigomegatwsq(iq_ibz)%free()
352 : end do
353 981 : ABI_FREE(ppm%bigomegatwsq)
354 : end if
355 233 : if (allocated(ppm%omegatw)) then
356 981 : do iq_ibz=1,dim_q
357 981 : call ppm%omegatw(iq_ibz)%free()
358 : end do
359 981 : ABI_FREE(ppm%omegatw)
360 : end if
361 233 : if (allocated(ppm%eigpot)) then
362 981 : do iq_ibz=1,dim_q
363 981 : call ppm%eigpot(iq_ibz)%free()
364 : end do
365 981 : ABI_FREE(ppm%eigpot)
366 : end if
367 :
368 : ! logical flags must be deallocated here.
369 233 : ABI_SFREE(ppm%keep_qibz)
370 233 : ABI_SFREE(ppm%has_qibz)
371 :
372 233 : end subroutine ppm_free
373 : !!***
374 :
375 : !----------------------------------------------------------------------
376 :
377 : !!****f* m_ppmodel/ppm_malloc_iqibz
378 : !! NAME
379 : !! ppm_malloc_iqibz
380 : !!
381 : !! FUNCTION
382 : !! Allocate the ppmodel tables for the selected q-point in the IBZ.
383 : !!
384 : !! INPUT
385 : !! iq_ibz=Index of the q-point in the IBZ.
386 : !!
387 : !! SOURCE
388 :
389 848 : subroutine ppm_malloc_iqibz(ppm, iq_ibz)
390 :
391 : !Arguments ------------------------------------
392 : class(ppmodel_t),intent(inout) :: ppm
393 : integer,intent(in) :: iq_ibz
394 :
395 : !Local variables-------------------------------
396 : integer :: ierr
397 : ! *********************************************************************
398 :
399 848 : ABI_CHECK(allocated(ppm%bigomegatwsq), "bigomegatwsq is not allocated")
400 848 : ABI_CHECK(allocated(ppm%omegatw), "omegatwsq is not allocated")
401 848 : ABI_CHECK(allocated(ppm%eigpot), "eigpot is not allocated")
402 :
403 848 : ABI_CHECK_IGEQ(size(ppm%bigomegatwsq), iq_ibz, "bigomegatwsq too small")
404 848 : ABI_CHECK_IGEQ(size(ppm%omegatw), iq_ibz, "omegatwsq too small")
405 848 : ABI_CHECK_IGEQ(size(ppm%eigpot), iq_ibz, "eigpot too small")
406 :
407 3392 : ABI_MALLOC_OR_DIE(ppm%bigomegatwsq(iq_ibz)%vals, (ppm%npwc, ppm%dm2_botsq), ierr)
408 3392 : ABI_MALLOC_OR_DIE(ppm%omegatw(iq_ibz)%vals, (ppm%npwc, ppm%dm2_otq), ierr)
409 3392 : ABI_MALLOC_OR_DIE(ppm%eigpot(iq_ibz)%vals, (ppm%dm_eig, ppm%dm_eig), ierr)
410 :
411 848 : ppm%has_qibz(iq_ibz) = PPM_TAB_ALLOCATED
412 :
413 848 : end subroutine ppm_malloc_iqibz
414 : !!***
415 :
416 : !----------------------------------------------------------------------
417 :
418 : !!****f* m_ppmodel/ppm_table_free_iqibz
419 : !! NAME
420 : !! ppm_table_free_iqibz
421 : !!
422 : !! FUNCTION
423 : !! Free the ppmodel tables for the selected q-point in the IBZ.
424 : !!
425 : !! INPUT
426 : !! iq_ibz = Index of the q-point in the IBZ.
427 : !!
428 : !! SOURCE
429 :
430 0 : subroutine ppm_table_free_iqibz(ppm, iq_ibz)
431 :
432 : !Arguments ------------------------------------
433 : class(ppmodel_t),intent(inout) :: ppm
434 : integer,intent(in) :: iq_ibz
435 : ! *********************************************************************
436 :
437 0 : if (allocated(ppm%bigomegatwsq)) call ppm%bigomegatwsq(iq_ibz)%free()
438 0 : if (allocated(ppm%omegatw)) call ppm%omegatw(iq_ibz)%free()
439 0 : if (allocated(ppm%eigpot)) call ppm%eigpot(iq_ibz)%free()
440 :
441 0 : ppm%has_qibz(iq_ibz) = PPM_NOTAB
442 :
443 0 : end subroutine ppm_table_free_iqibz
444 : !!***
445 :
446 : !----------------------------------------------------------------------
447 :
448 : !!****f* m_ppmodel/ppm_init
449 : !! NAME
450 : !! ppm_init
451 : !!
452 : !! FUNCTION
453 : !! Initialize dimensions and other important variables related to the ppmodel
454 : !!
455 : !! INPUTS
456 : !! ppmodel=
457 : !! drude_plsmf=
458 : !!
459 : !! SOURCE
460 :
461 133 : subroutine ppm_init(ppm, mqmem, nqibz, npwe, ppmodel, drude_plsmf, invalid_freq)
462 :
463 : !Arguments ------------------------------------
464 : class(ppmodel_t),intent(out) :: ppm
465 : integer,intent(in) :: mqmem, nqibz, npwe, ppmodel, invalid_freq
466 : real(dp),intent(in) :: drude_plsmf
467 :
468 : !Local variables-------------------------------
469 : !scalars
470 : integer :: dim_q,iq_ibz
471 : logical :: ltest
472 : !character(len=500) :: msg
473 : ! *********************************************************************
474 :
475 133 : ppm%nqibz = nqibz; ppm%mqmem = mqmem; ppm%invalid_freq = invalid_freq
476 : !call wrtout(std_out, sjoin(' ppm%mqmem:', itoa(ppm%mqmem), 'ppm%nqibz:', itoa(ppm%nqibz)))
477 : ltest = (ppm%mqmem == 0 .or. ppm%mqmem == ppm%nqibz)
478 : ! ABI_CHECK(ltest,'Wrong value for mqmem')
479 :
480 133 : ppm%npwc = npwe
481 133 : ppm%model = ppmodel
482 133 : ppm%drude_plsmf = drude_plsmf
483 133 : ppm%userho = 0
484 133 : if (any(ppmodel == [PPM_HYBERTSEN_LOUIE, PPM_LINDEN_HORSH, PPM_ENGEL_FARID])) ppm%userho = 1
485 :
486 399 : ABI_MALLOC(ppm%keep_qibz, (nqibz))
487 1831 : ppm%keep_qibz = .FALSE.; if (ppm%mqmem > 0) ppm%keep_qibz = .TRUE.
488 :
489 266 : ABI_MALLOC(ppm%has_qibz, (nqibz))
490 1000 : ppm%has_qibz = PPM_NOTAB
491 :
492 : ! Full q-mesh is stored or out-of-memory solution.
493 133 : dim_q = ppm%nqibz; if (ppm%mqmem == 0) dim_q=1
494 :
495 1247 : ABI_MALLOC(ppm%bigomegatwsq, (dim_q))
496 1114 : ABI_MALLOC(ppm%omegatw, (dim_q))
497 1114 : ABI_MALLOC(ppm%eigpot, (dim_q))
498 :
499 133 : select case (ppm%model)
500 : case (PPM_NONE)
501 0 : ABI_WARNING("Called with ppmodel == 0")
502 0 : ppm%dm2_botsq = 0
503 0 : ppm%dm2_otq = 0
504 0 : ppm%dm_eig = 0
505 0 : RETURN
506 :
507 : case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
508 127 : ppm%dm2_botsq = ppm%npwc
509 127 : ppm%dm2_otq = ppm%npwc
510 127 : ppm%dm_eig = 1 ! Should be set to 0, but g95 does not like zero-sized arrays
511 :
512 : case (PPM_LINDEN_HORSH)
513 3 : ppm%dm2_botsq = 1
514 3 : ppm%dm2_otq = 1
515 3 : ppm%dm_eig = ppm%npwc
516 :
517 : case (PPM_ENGEL_FARID)
518 3 : ppm%dm2_botsq = ppm%npwc
519 3 : ppm%dm2_otq = 1
520 3 : ppm%dm_eig = 1 ! Should be set to 0, but g95 does not like zero-sized arrays
521 :
522 : case default
523 133 : ABI_BUG(sjoin('Wrong ppm%model:', itoa(ppm%model)))
524 : end select
525 :
526 : ! Allocate tables depending on the value of keep_qibz.
527 981 : do iq_ibz=1,dim_q
528 981 : call ppm%malloc_iqibz(iq_ibz)
529 : end do
530 :
531 133 : call pstat_proc%print(_PSTAT_ARGS_)
532 :
533 : end subroutine ppm_init
534 : !!***
535 :
536 : !----------------------------------------------------------------------
537 :
538 : !!****f* m_ppmodel/ppm_setup
539 : !! NAME
540 : !! ppm_setup
541 : !!
542 : !! FUNCTION
543 : !! Initialize some values of several arrays of the ppm datastructure
544 : !! that are used in case of plasmonpole calculations
545 : !! This is a wrapper around different plasmonpole routines.
546 : !!
547 : !! INPUTS
548 : !! Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
549 : !! Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
550 : !! npwe=number of G vectors for the correlation part
551 : !! nomega=number of frequencies in $\epsilon^{-1}$
552 : !! omega=frequencies in epsm1
553 : !! epsm1=the inverse dielctric matrix
554 : !! ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
555 : !! gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
556 : !! nfftf=the number of points in the FFT mesh (for this processor)
557 : !! rhor_tot(nfftf)=the total charge in real space
558 : !!
559 : !! SIDE EFFECTS
560 : !! == if ppmodel 1 or 2 ==
561 : !! %omegatw and %bigomegatwsq
562 : !! == if ppmodel 3 ==
563 : !! %omegatw, %bigomegatwsq and %eigpot
564 : !! == if ppmodel 4 ==
565 : !! %omegatw and %bigomegatwsq
566 : !!
567 : !! NOTES
568 : !! * FFT parallelism not implemented.
569 : !! * TODO: rhor_tot should be replaced by rhog_tot
570 : !!
571 : !! SOURCE
572 :
573 403 : subroutine ppm_setup(ppm, Cryst, Qmesh, npwe, nomega, omega, epsm1, nfftf, gvec, ngfftf, rhor_tot, &
574 : iqiA) ! Optional
575 :
576 : !Arguments ------------------------------------
577 : !scalars
578 : class(ppmodel_t),intent(inout) :: ppm
579 : integer,intent(in) :: nfftf,npwe,nomega
580 : integer,intent(in),optional :: iqiA
581 : type(kmesh_t),intent(in) :: Qmesh
582 : type(crystal_t),intent(in) :: Cryst
583 : !arrays
584 : integer,intent(in) :: gvec(3,npwe),ngfftf(18)
585 : real(dp),intent(in) :: rhor_tot(nfftf)
586 : complex(dp),intent(in) :: omega(nomega)
587 : complex(gwp),intent(in) :: epsm1(:,:,:,:)
588 :
589 : !Local variables-------------------------------
590 : !scalars
591 : integer :: nqiA,iq_ibz
592 : real(dp) :: n_at_G_zero
593 : logical :: single_q
594 : character(len=500) :: msg
595 : !scalars
596 : real(dp) :: qpt(3)
597 : ! *************************************************************************
598 :
599 : !@ppmodel_t
600 : !
601 : ! === if iqiA is present, then consider only one qpoint to save memory ===
602 : ! * This means the object has been already initialized
603 403 : nqiA = Qmesh%nibz; single_q = .FALSE.
604 403 : if (PRESENT(iqiA)) then
605 290 : nqiA = 1; single_q = .TRUE.
606 : end if
607 :
608 : ! Allocate plasmonpole parameters
609 : ! TODO ppmodel==1 by default, should be set to 0 if AC and CD
610 403 : select case (ppm%model)
611 :
612 : case (PPM_NONE)
613 0 : ABI_COMMENT(' Skipping Plasmompole model calculation')
614 :
615 : case (PPM_GODBY_NEEDS)
616 : ! Note: the q-dependency enters only through epsilon^-1.
617 1435 : do iq_ibz=1,nqiA
618 : call cppm1par(npwe,nomega,omega,ppm%drude_plsmf,&
619 1435 : epsm1(:,:,:,iq_ibz),ppm%omegatw(iq_ibz)%vals,ppm%bigomegatwsq(iq_ibz)%vals)
620 : end do
621 :
622 : case (PPM_HYBERTSEN_LOUIE)
623 28 : do iq_ibz=1,nqiA
624 96 : qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
625 :
626 : call cppm2par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,Cryst%gmet,&
627 28 : ppm%bigomegatwsq(iq_ibz)%vals,ppm%omegatw(iq_ibz)%vals,ppm%invalid_freq)
628 : end do
629 :
630 : ! Quick-and-dirty change of the plasma frequency. Never executed in standard runs.
631 4 : if (ppm%force_plsmf>tol6) then ! Integrate the real-space density
632 0 : n_at_G_zero = SUM(rhor_tot(:))/nfftf
633 : ! Change the prefactor
634 0 : write(msg,'(2(a,es16.8))') 'Forced ppmfreq:',ppm%force_plsmf*Ha_eV,' nelec/ucvol:',n_at_G_zero
635 0 : ABI_WARNING(msg)
636 0 : ppm%force_plsmf = (ppm%force_plsmf**2)/(four_pi*n_at_G_zero)
637 0 : do iq_ibz=1,ppm%nqibz
638 0 : ppm%bigomegatwsq(iq_ibz)%vals = ppm%force_plsmf * ppm%bigomegatwsq(iq_ibz)%vals
639 0 : ppm%omegatw(iq_ibz)%vals = ppm%force_plsmf * ppm%omegatw(iq_ibz)%vals
640 : end do
641 0 : write(msg,'(a,es16.8)') 'Plasma frequency forced in HL ppmodel, new prefactor is:',ppm%force_plsmf
642 0 : ABI_WARNING(msg)
643 : end if
644 :
645 : case (PPM_LINDEN_HORSH) ! TODO Check better double precision, this routine is in a messy state
646 21 : do iq_ibz=1,nqiA
647 72 : qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
648 : call cppm3par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
649 21 : ppm%bigomegatwsq(iq_ibz)%vals,ppm%omegatw(iq_ibz)%vals(:,1),ppm%eigpot(iq_ibz)%vals)
650 : end do
651 :
652 : case (PPM_ENGEL_FARID) ! TODO Check better double precision, this routine is in a messy state
653 21 : do iq_ibz=1,nqiA
654 72 : qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
655 30 : if ((ALL(ABS(qpt)<1.0e-3))) qpt = GW_Q0_DEFAULT ! FIXME
656 : call cppm4par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
657 21 : ppm%bigomegatwsq(iq_ibz)%vals,ppm%omegatw(iq_ibz)%vals(:,1))
658 : end do
659 :
660 : case default
661 403 : ABI_BUG(sjoin('Wrong ppm%model:',itoa(ppm%model)))
662 : end select
663 :
664 403 : end subroutine ppm_setup
665 : !!***
666 :
667 : !----------------------------------------------------------------------
668 :
669 : !!****f* m_ppmodel/ppm_getem1
670 : !! NAME
671 : !! ppm_getem1
672 : !!
673 : !! FUNCTION
674 : !! Calculate the symmetrized inverse dielectric matrix from the parameters of the plasmon-pole model.
675 : !!
676 : !! INPUTS
677 : !!
678 : !! OUTPUT
679 : !!
680 : !! SOURCE
681 :
682 0 : subroutine ppm_getem1(ppm, mpwc, iqibz, zcut, nomega, omega, Vcp, em1q, &
683 : only_ig1, only_ig2) ! Optional
684 :
685 : !Arguments ------------------------------------
686 : !scalars
687 : class(ppmodel_t),intent(in) :: ppm
688 : integer,intent(in) :: mpwc,iqibz,nomega
689 : type(vcoul_t),intent(in) :: Vcp
690 : real(dp),intent(in) :: zcut
691 : integer,optional,intent(in) :: only_ig1,only_ig2
692 : !arrays
693 : complex(dp),intent(in) :: omega(nomega)
694 : complex(dp),intent(out) :: em1q(mpwc,mpwc,nomega)
695 :
696 : !Local variables-------------------------------
697 : !scalars
698 : integer :: ig1,ig2,io,idm,ig1_min,ig2_min,ig1_max,ig2_max
699 : real(dp) :: den
700 : complex(dp) :: qpg1,qpg2,ug1,ug2
701 : complex(dp) :: delta,em1ggp,otw,zzpq,yg1,yg2,bot1,bot2,chig1g2
702 : !character(len=500) :: msg
703 : ! *************************************************************************
704 :
705 0 : ABI_CHECK(ppm%mqmem/=0,'mqmem==0 not implemented')
706 :
707 : !TODO zcut should be an entry in ppm
708 0 : delta=CMPLX(zero,zcut)
709 :
710 : ! To save memory, a particular combination of
711 : ! ig1 and ig2 can be selected
712 0 : ig1_min = 1
713 0 : ig2_min = 1
714 0 : ig1_max = ppm%npwc
715 0 : ig2_max = ppm%npwc
716 0 : if (present(only_ig1)) then
717 0 : ig1_min = only_ig1
718 0 : ig1_max = only_ig1
719 : end if
720 0 : if (present(only_ig2)) then
721 0 : ig2_min = only_ig2
722 0 : ig2_max = only_ig2
723 : end if
724 :
725 0 : select case (ppm%model)
726 : case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
727 0 : do io=1,nomega
728 0 : do ig2=ig2_min,ig2_max
729 0 : do ig1=ig1_min,ig1_max
730 : !den = omega(io)**2-REAL(ppm%omegatw(iqibz)%vals(ig1,ig2)**2)
731 : !if (den**2<zcut**2) den = omega(io)**2-REAL( (ppm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
732 0 : den = omega(io)**2 - REAL( (ppm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
733 0 : em1ggp = ppm%bigomegatwsq(iqibz)%vals(ig1,ig2)/den
734 0 : if (ig1==ig2) em1ggp=em1ggp+one
735 0 : em1q(ig1,ig2,io)=em1ggp
736 : !em1q(ig1,ig2,io)=em1ggp*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
737 : end do
738 : end do
739 : !
740 : end do !io
741 :
742 : case (PPM_LINDEN_HORSH)
743 : !TODO Check coefficients
744 0 : do io=1,nomega
745 0 : do ig2=ig2_min,ig2_max
746 0 : do ig1=ig1_min,ig1_max
747 : !
748 : em1ggp=czero
749 0 : do idm=1,ppm%npwc
750 : !den=omega(io)**2-(ppm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2
751 : !em1w(io)=em1w(io)+eigvec(ig1,idm,iqibz)*conjg(eigvec(ig2,idm,iqibz))*bigomegatwsq(ig1,ig2,iqibz)/den
752 0 : ug1 = ppm%eigpot(iqibz)%vals(ig1,idm)
753 0 : ug2 = ppm%eigpot(iqibz)%vals(ig2,idm)
754 0 : otw = ppm%bigomegatwsq(iqibz)%vals(idm,1)*ppm%omegatw(iqibz)%vals(idm,1)
755 0 : zzpq=ppm%bigomegatwsq(iqibz)%vals(idm,1)
756 0 : den=half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
757 0 : em1ggp=em1ggp+ug1*CONJG(ug2)*den
758 : !eigenvalues(idm,io)=one + half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
759 : end do
760 0 : if (ig2==ig1) em1ggp=em1ggp+one
761 0 : em1q(ig1,ig2,io)=em1ggp
762 : end do !ig1
763 : end do !ig2
764 : !
765 : end do !iomega
766 :
767 : case (PPM_ENGEL_FARID)
768 : ! Make e^-1
769 0 : do io=1,nomega
770 0 : do ig2=ig2_min,ig2_max
771 0 : qpg2=one/Vcp%vc_sqrt(ig2,iqibz)
772 0 : do ig1=ig1_min,ig1_max
773 0 : qpg1=one/Vcp%vc_sqrt(ig1,iqibz)
774 :
775 0 : chig1g2=czero
776 0 : do idm=1,ppm%npwc
777 0 : otw =ppm%omegatw(iqibz)%vals(idm,1)
778 0 : bot1=ppm%bigomegatwsq(iqibz)%vals(ig1,idm)
779 0 : bot2=ppm%bigomegatwsq(iqibz)%vals(ig2,idm)
780 0 : yg1=SQRT(otw/four_pi)*qpg1*bot1
781 0 : yg2=SQRT(otw/four_pi)*qpg2*bot2
782 0 : chig1g2=chig1g2 + yg1*CONJG(yg2)/(omega(io)**2-(otw-delta)**2)
783 : end do
784 :
785 0 : em1ggp=four_pi*chig1g2/(qpg1*qpg2)
786 0 : if (ig1==ig2) em1ggp=em1ggp+one
787 0 : em1q(ig1,ig2,io)=em1ggp !*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
788 : end do !ig1
789 : end do !ig2
790 : end do !iomega
791 :
792 : case default
793 0 : ABI_BUG(sjoin('Wrong ppm%model:',itoa(ppm%model)))
794 : end select
795 :
796 0 : end subroutine ppm_getem1
797 : !!***
798 :
799 : !----------------------------------------------------------------------
800 :
801 : !!****f* m_ppmodel/ppm_getem1_one_ggp
802 : !! NAME
803 : !! ppm_getem1_one_ggp
804 : !!
805 : !! FUNCTION
806 : !! Same as ppm_getem1, but does it for a single set of G,G' vectors
807 : !!
808 : !! INPUTS
809 : !!
810 : !! OUTPUT
811 : !!
812 : !! SOURCE
813 :
814 0 : subroutine ppm_getem1_one_ggp(ppm, iqibz, zcut, nomega, omega, Vcp, em1q, ig1, ig2)
815 :
816 : !Arguments ------------------------------------
817 : !scalars
818 : class(ppmodel_t),intent(in) :: ppm
819 : integer,intent(in) :: iqibz,nomega
820 : type(vcoul_t),intent(in) :: Vcp
821 : real(dp),intent(in) :: zcut
822 : integer, intent(in) :: ig1,ig2
823 : !arrays
824 : complex(dp),intent(in) :: omega(nomega)
825 : complex(dp),intent(out) :: em1q(nomega)
826 :
827 : !Local variables-------------------------------
828 : !scalars
829 : integer :: io,idm !,ig1_min,ig2_min,ig2_max
830 : real(dp) :: den
831 : complex(dp) :: qpg1,qpg2,ug1,ug2
832 : complex(dp) :: delta,em1ggp,otw,zzpq,yg1,yg2,bot1,bot2,chig1g2
833 : !character(len=500) :: msg
834 : ! *************************************************************************
835 :
836 0 : ABI_CHECK(ppm%mqmem /= 0, 'mqmem==0 not implemented')
837 :
838 : !TODO zcut should be an entry in ppm
839 0 : delta=CMPLX(zero,zcut)
840 :
841 0 : select case (ppm%model)
842 :
843 : case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
844 0 : do io=1,nomega
845 : !den = omega(io)**2-REAL(ppm%omegatw(iqibz)%vals(ig1,ig2)**2)
846 : !if (den**2<zcut**2) den = omega(io)**2-REAL( (ppm%omegatw(iqibz)%value(ig1,ig2)-delta)**2 )
847 0 : den = omega(io)**2-REAL( (ppm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
848 0 : em1ggp = ppm%bigomegatwsq(iqibz)%vals(ig1,ig2)/den
849 0 : if (ig1==ig2) em1ggp=em1ggp+one
850 0 : em1q(io)=em1ggp
851 : !em1q(io)=em1ggp*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
852 : end do !io
853 :
854 : case (PPM_LINDEN_HORSH)
855 : !TODO Check coefficients
856 0 : do io=1,nomega
857 0 : em1ggp=czero
858 0 : do idm=1,ppm%npwc
859 : !den=omega(io)**2-(ppm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2
860 : !em1w(io)=em1w(io)+eigvec(ig1,idm,iqibz)*conjg(eigvec(ig2,idm,iqibz))*bigomegatwsq(ig1,ig2,iqibz)/den
861 0 : ug1 =ppm%eigpot(iqibz)%vals(ig1,idm)
862 0 : ug2 =ppm%eigpot(iqibz)%vals(ig2,idm)
863 0 : otw =ppm%bigomegatwsq(iqibz)%vals(idm,1)*ppm%omegatw(iqibz)%vals(idm,1)
864 0 : zzpq=ppm%bigomegatwsq(iqibz)%vals(idm,1)
865 0 : den=half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
866 0 : em1ggp=em1ggp+ug1*CONJG(ug2)*den
867 : !eigenvalues(idm,io)=one + half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
868 : end do
869 :
870 0 : if (ig2==ig1) em1ggp=em1ggp+one
871 0 : em1q(io)=em1ggp
872 : end do !iomega
873 :
874 : case (PPM_ENGEL_FARID)
875 : ! Make e^-1
876 0 : do io=1,nomega
877 0 : qpg2=one/Vcp%vc_sqrt(ig2,iqibz)
878 0 : qpg1=one/Vcp%vc_sqrt(ig1,iqibz)
879 :
880 0 : chig1g2=czero
881 0 : do idm=1,ppm%npwc
882 0 : otw =ppm%omegatw(iqibz)%vals(idm,1)
883 0 : bot1=ppm%bigomegatwsq(iqibz)%vals(ig1,idm)
884 0 : bot2=ppm%bigomegatwsq(iqibz)%vals(ig2,idm)
885 0 : yg1=SQRT(otw/four_pi)*qpg1*bot1
886 0 : yg2=SQRT(otw/four_pi)*qpg2*bot2
887 0 : chig1g2=chig1g2 + yg1*CONJG(yg2)/(omega(io)**2-(otw-delta)**2)
888 : end do
889 :
890 0 : em1ggp=four_pi*chig1g2/(qpg1*qpg2)
891 0 : if (ig1==ig2) em1ggp=em1ggp+one
892 0 : em1q(io)=em1ggp !*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
893 : end do ! io
894 :
895 : case default
896 0 : ABI_BUG(sjoin('Wrong ppm%model:',itoa(ppm%model)))
897 : end select
898 :
899 0 : end subroutine ppm_getem1_one_ggp
900 : !!***
901 :
902 : !----------------------------------------------------------------------
903 :
904 : !!****f* m_ppmodel/ppm_get_eigenvalues
905 : !! NAME
906 : !! ppm_get_eigenvalues
907 : !!
908 : !! FUNCTION
909 : !! Constructs the inverse dielectri matrixc starting from the plasmon-pole
910 : !! parameters and calculates the frequency-dependent eigenvalues for each
911 : !! of the nomega frequencies specified in the array omega.
912 : !!
913 : !! INPUTS
914 : !!
915 : !! OUTPUT
916 : !!
917 : !! SOURCE
918 :
919 0 : subroutine ppm_get_eigenvalues(ppm, iqibz, zcut, nomega, omega, Vcp, eigenvalues)
920 :
921 : !Arguments ------------------------------------
922 : !scalars
923 : class(ppmodel_t),intent(in) :: ppm
924 : integer,intent(in) :: iqibz,nomega
925 : type(vcoul_t),intent(in) :: Vcp
926 : real(dp),intent(in) :: zcut
927 : !arrays
928 : complex(dp),intent(in) :: omega(nomega)
929 : complex(dp),intent(out) :: eigenvalues(ppm%npwc,nomega)
930 :
931 : !Local variables-------------------------------
932 : !scalars
933 : integer :: info,lwork,negw,ig1,ig2,idx,sdim,iomega,ierr
934 : character(len=500) :: msg
935 : !arrays
936 0 : real(dp),allocatable :: ww(:),rwork(:)
937 0 : complex(dp),allocatable :: work(:),Adpp(:),eigvec(:,:),wwc(:),vs(:,:),Afull(:,:)
938 0 : complex(dp),allocatable :: em1q(:,:,:)
939 0 : logical,allocatable :: bwork(:)
940 : logical :: sortcplx !BUG in abilint
941 : ! *************************************************************************
942 :
943 0 : ABI_CHECK(ppm%mqmem/=0,'mqmem==0 not implemented')
944 :
945 0 : ABI_MALLOC(em1q, (ppm%npwc,ppm%npwc,nomega))
946 :
947 0 : call ppm%getem1(ppm%npwc,iqibz,zcut,nomega,omega,Vcp,em1q)
948 :
949 0 : do iomega=1,nomega
950 0 : if (ABS(REAL(omega(iomega)))>0.00001) then
951 : ! Eigenvalues for a generic complex matrix.
952 :
953 0 : lwork=4*2*ppm%npwc
954 0 : ABI_MALLOC(wwc,(ppm%npwc))
955 0 : ABI_MALLOC(work,(lwork))
956 0 : ABI_MALLOC(rwork,(ppm%npwc))
957 0 : ABI_MALLOC(bwork,(ppm%npwc))
958 0 : ABI_MALLOC(vs,(ppm%npwc,ppm%npwc))
959 0 : ABI_MALLOC(Afull,(ppm%npwc,ppm%npwc))
960 0 : Afull=em1q(:,:,iomega)
961 :
962 : !for the time being, no sorting. Maybe here I should sort using the real part?
963 0 : call ZGEES('V','N',sortcplx,ppm%npwc,Afull,ppm%npwc,sdim,wwc,vs,ppm%npwc,work,lwork,rwork,bwork,info)
964 0 : if (info/=0) then
965 0 : write(msg,'(2a,i10)')' ppm_get_eigenvalues: Error in ZGEES, diagonalizing complex matrix, info = ',info
966 0 : call wrtout(std_out,msg)
967 : end if
968 :
969 0 : eigenvalues(:,iomega)=wwc(:)
970 :
971 0 : ABI_FREE(wwc)
972 0 : ABI_FREE(work)
973 0 : ABI_FREE(rwork)
974 0 : ABI_FREE(bwork)
975 0 : ABI_FREE(vs)
976 0 : ABI_FREE(Afull)
977 :
978 : else
979 : ! === Hermitian Case ===
980 0 : lwork=2*ppm%npwc-1
981 0 : ABI_MALLOC(ww,(ppm%npwc))
982 0 : ABI_MALLOC(work,(lwork))
983 0 : ABI_MALLOC(rwork,(3*ppm%npwc-2))
984 0 : ABI_MALLOC(eigvec,(ppm%npwc,ppm%npwc))
985 :
986 0 : ABI_MALLOC_OR_DIE(Adpp,(ppm%npwc*(ppm%npwc+1)/2), ierr)
987 : !write(std_out,*) 'in hermitian'
988 :
989 0 : idx=0
990 0 : do ig2=1,ppm%npwc
991 0 : do ig1=1,ig2
992 0 : idx=idx+1
993 0 : Adpp(idx)=em1q(ig1,ig2,iomega)
994 : end do
995 : end do
996 :
997 : ! Require eigenvectors as well
998 0 : call ZHPEV('V','U',ppm%npwc,Adpp,ww,eigvec,ppm%npwc,work,rwork,info)
999 :
1000 0 : ABI_CHECK(info == 0, sjoin('Error diagonalizing matrix, info: ', itoa(info)))
1001 :
1002 0 : negw = (COUNT((REAL(ww)<tol6)))
1003 0 : if (negw /= 0) then
1004 0 : write(msg,'(a,i0,a,i0,a,f8.4)')'Found negative eigenvalues. No. ',negw,' at iqibz= ',iqibz,' minval= ',MINVAL(REAL(ww))
1005 0 : ABI_WARNING(msg)
1006 : end if
1007 :
1008 0 : eigenvalues(:,iomega)=ww(:)
1009 :
1010 0 : ABI_FREE(ww)
1011 0 : ABI_FREE(work)
1012 0 : ABI_FREE(rwork)
1013 0 : ABI_FREE(eigvec)
1014 0 : ABI_FREE(Adpp)
1015 : end if
1016 : end do !iomega
1017 :
1018 0 : ABI_FREE(em1q)
1019 :
1020 0 : end subroutine ppm_get_eigenvalues
1021 : !!***
1022 :
1023 : !----------------------------------------------------------------------
1024 :
1025 : !!****f* m_ppmodel/cppm1par
1026 : !! NAME
1027 : !! cppm1par
1028 : !!
1029 : !! FUNCTION
1030 : !! Calculate the plasmon-pole parameters big-omega-twiddle-squared and omega-twiddle from
1031 : !! epsilon-twiddle^-1 calculated for nomega (usually 2) frequencies omega=0 and omega=iE0.
1032 : !!
1033 : !! INPUTS
1034 : !! epsm1(npwc,npwc,nomega)=dielectric matrix at nomega frequencies.
1035 : !! npwc=number of plane waves
1036 : !! nomega=number of frequencies (usually 2)
1037 : !! omega(nomega)=frequencies
1038 : !! omegaplasma=input variable or Drude plasma frequency
1039 : !!
1040 : !! OUTPUT
1041 : !! bigomegatwsq(npwc,npwc)=parameter of the plasmon-pole model (see gwa.pdf file)
1042 : !! omegatw(npwc,npwc)=parameter of the plasmon-pole model (see gwa.pdf file)
1043 : !!
1044 : !! TODO
1045 : !! Calculation can be done in place.
1046 : !!
1047 : !! SOURCE
1048 :
1049 1061 : subroutine cppm1par(npwc, nomega, omega, omegaplasma, epsm1, omegatw, bigomegatwsq)
1050 :
1051 : !Arguments ------------------------------------
1052 : !scalars
1053 : integer,intent(in) :: nomega,npwc
1054 : real(dp),intent(in) :: omegaplasma
1055 : !arrays
1056 : complex(dp),intent(in) :: omega(nomega)
1057 : complex(gwp),intent(in) :: epsm1(npwc,npwc,nomega)
1058 : complex(gwp),intent(out) :: omegatw(npwc,npwc), bigomegatwsq(npwc,npwc)
1059 :
1060 : !Local variables-------------------------------
1061 : !scalars
1062 : integer :: ig,igp,io,io0,ioe0
1063 : real(dp) :: e0,minomega
1064 : character(len=500) :: msg
1065 : complex(gwp) :: AA,omegatwsq,diff,ratio,epsm1_io0,epsm1_ioe0
1066 : ! *************************************************************************
1067 :
1068 : ! Find omega=0 and omega=imag (closest to omegaplasma) to fit the ppm parameters
1069 1061 : minomega=1.0d-3; io0=0
1070 3334 : do io=1,nomega
1071 3334 : if (ABS(omega(io))<minomega) then
1072 1061 : io0=io; minomega=ABS(omega(io))
1073 : end if
1074 : end do
1075 1061 : ABI_CHECK(io0 /= 0, "omega=0 not found")
1076 :
1077 1061 : minomega=1.0d-3; e0=200.0; ioe0=0
1078 3334 : do io=1,nomega
1079 3334 : if (REAL(omega(io))<minomega.and.AIMAG(omega(io))>minomega) then
1080 1121 : if (ABS(AIMAG(omega(io))-omegaplasma)<ABS(e0-omegaplasma)) then
1081 2273 : ioe0=io; e0=AIMAG(omega(io))
1082 : end if
1083 : end if
1084 : end do
1085 :
1086 1061 : write(msg,'(a,f9.4,a)')' Imaginary frequency for fit located at: ',e0*Ha_eV,' [eV] '
1087 1061 : call wrtout(std_out, msg)
1088 1061 : ABI_CHECK(ioe0 /= 0,"Imaginary omega not found")
1089 :
1090 : ! ================================================================
1091 : ! === Calculate plasmon-pole A parameter A=epsilon^-1(0)-delta ===
1092 : ! ================================================================
1093 53290 : do ig=1,npwc
1094 4125335 : do igp=1,npwc
1095 4072045 : epsm1_io0 = epsm1(ig,igp,io0)
1096 4072045 : epsm1_ioe0 = epsm1(ig,igp,ioe0)
1097 :
1098 4072045 : AA=epsm1_io0
1099 4072045 : if (ig==igp) AA=AA-one
1100 :
1101 : ! === Calculate plasmon-pole omega-twiddle-square parameter ===
1102 : ! XG201009 Strangely, the next formula does not work with gcc43-debug
1103 : ! omegatwsq=(AA/(epsm1_io0-epsm1_ioe0)-one)*e0**2
1104 : ! This seems to be due to precision issue at the level of division by a complex whose norm squared
1105 : ! is below the smallest representable number.
1106 : ! After many trials, I have decided to shift the difference by a small number ... well, not so small ...
1107 : ! for numerical issues
1108 4072045 : diff=epsm1_io0-epsm1_ioe0
1109 4072045 : diff=diff+cmplx(tol10,tol10)
1110 4072045 : ratio=AA/diff
1111 4072045 : omegatwsq=(ratio-cone)*e0**2
1112 : !
1113 : ! If omega-twiddle-squared is negative,set omega-twiddle-squared to 1.0 (a reasonable way of treating
1114 : ! such terms, in which epsilon**-1 was originally increasing along this part of the imaginary axis)
1115 : ! (note: originally these terms were ignored in Sigma; this was changed on 6 March 1990.)
1116 :
1117 4072045 : if (REAL(omegatwsq)<=zero) omegatwsq=one
1118 : !
1119 : ! Get omega-twiddle. Neglect the imag part (if any) in omega-twiddle-squared
1120 4072045 : omegatw(ig,igp)=SQRT(REAL(omegatwsq))
1121 :
1122 : ! Get big-omega-twiddle-squared=-omega-twiddle-squared AA
1123 4124274 : bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1124 :
1125 : end do !igp
1126 : end do !ig
1127 :
1128 1061 : write(msg,'(2a,f15.12,2a,2i5,a)')ch10,&
1129 4125335 : ' cppm1par : omega twiddle minval [eV] = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1130 4128518 : ' omega twiddle min location = ',MINLOC(ABS(omegatw)),ch10
1131 1061 : call wrtout(std_out,msg)
1132 :
1133 1061 : end subroutine cppm1par
1134 : !!***
1135 :
1136 : !----------------------------------------------------------------------
1137 :
1138 : !!****f* m_ppmodel/cppm2par
1139 : !! NAME
1140 : !! cppm2par
1141 : !!
1142 : !! FUNCTION
1143 : !! Calculate plasmon-pole parameters of the Hybertsen and Louie model (PRB 34, 5390 (1986) [[cite:Hybertsen1986]])
1144 : !!
1145 : !! INPUTS
1146 : !! qpt(3)=The coordinates of the q-point in the IBZ.
1147 : !! epsm1(npwc,npwc)=symmetrized inverse dielectric (static limit is used)
1148 : !! gmet(3,3)=metric in reciprocal space
1149 : !! ngfftf(18)=contain all needed information about the 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
1150 : !! npwc=number of plane waves in epsm1
1151 : !! rhor(nfftf)=charge density on the real space FFT grid
1152 : !! nfftf= total number of points in the fine FFT mesh (for this processor)
1153 : !! invalid_freq: what to do when PPM omega is found negative or imaginary
1154 : !! 0) drop it (default as specified in Hybersen-Louie original GW paper)
1155 : !! 1) set to 1 hartree
1156 : !! 2) set to infinity
1157 : !!
1158 : !! OUTPUT
1159 : !! bigomegatwsq(npwc,npwc)= squared bare plasma frequencies
1160 : !! \Omega^2_{G1 G2}(q) = 4\pi \frac {(q+G1).(q+G2)}/{|q+G1|^2} n(G1-G2)
1161 : !! omegatw(npwc,npwc)= plasmon frequencies \tilde\omega_{G1 G2}(q) where:
1162 : !! \tilde\omega^2_{G1 G2}(q) =
1163 : !! \frac {\Omega^2_{G1 G2}(q)} {\delta_{G1 G2}-\tilde\epsilon^{-1}_{G1 G2} (q, \omega=0)}
1164 : !!
1165 : !! SOURCE
1166 :
1167 24 : subroutine cppm2par(qpt, npwc, epsm1, ngfftf, gvec, gprimd, rhor, nfftf, gmet, bigomegatwsq, omegatw, invalid_freq)
1168 :
1169 : !Arguments ------------------------------------
1170 : !scalars
1171 : integer,intent(in) :: npwc,nfftf,invalid_freq
1172 : !arrays
1173 : integer,intent(in) :: gvec(3,npwc), ngfftf(18)
1174 : real(dp),intent(in) :: qpt(3),gmet(3,3),gprimd(3,3), rhor(nfftf)
1175 : complex(gwp),intent(in) :: epsm1(npwc,npwc)
1176 : complex(gwp),intent(out) :: bigomegatwsq(npwc,npwc), omegatw(npwc,npwc)
1177 :
1178 : !Local variables-------------------------------
1179 : !scalars
1180 : integer :: ig,igp,nimwp,ngfft1,ngfft2,ngfft3,gmgp_idx,ierr
1181 : real(dp) :: lambda,phi,AA
1182 : logical,parameter :: use_symmetrized=.TRUE., check_imppf=.FALSE.
1183 : character(len=500) :: msg
1184 24 : type(MPI_type) :: MPI_enreg_seq
1185 : !arrays
1186 : real(dp) :: qlist(3,1)
1187 24 : real(dp),allocatable :: tmp_rhor(:),qratio(:,:),qplusg(:),rhog_dp(:,:)
1188 24 : complex(gwp),allocatable :: omegatwsq(:,:)
1189 24 : complex(gwp),allocatable :: rhog(:),rhogg(:,:),temp(:,:) !MG these should be double precision TODO
1190 : !*************************************************************************
1191 :
1192 24 : call initmpi_seq(MPI_enreg_seq)
1193 24 : call MPI_enreg_seq%distribfft%init_seq('c',ngfftf(2),ngfftf(3),'all')
1194 :
1195 : ! Calculate qratio(npwec,npvec) = (q+G).(q+Gp)/|q+G|^2 ===
1196 96 : ABI_MALLOC_OR_DIE(qratio,(npwc,npwc), ierr)
1197 :
1198 24 : call cqratio(npwc,gvec,qpt,gmet,gprimd,qratio)
1199 : !
1200 : ! Compute the density in G space rhor(R)--> rhog(G)
1201 72 : ABI_MALLOC(rhog_dp,(2,nfftf))
1202 72 : ABI_MALLOC(rhog,(nfftf))
1203 24 : ngfft1=ngfftf(1); ngfft2=ngfftf(2); ngfft3=ngfftf(3)
1204 :
1205 72 : ABI_MALLOC(tmp_rhor,(nfftf))
1206 183222 : tmp_rhor = rhor ! To avoid having to use intent(inout).
1207 24 : call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1208 24 : ABI_FREE(tmp_rhor)
1209 :
1210 183198 : rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1211 :
1212 : ! Calculate the FFT index of each (G-Gp) vector and assign
1213 : ! the value of the correspondent density simultaneously
1214 96 : ABI_MALLOC_OR_DIE(rhogg,(npwc, npwc), ierr)
1215 :
1216 24 : ierr=0
1217 708 : do ig=1,npwc
1218 20364 : do igp=1,npwc
1219 78624 : gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1220 20340 : if (gmgp_idx/=0) then
1221 19656 : rhogg(ig,igp)=rhog(gmgp_idx)
1222 : else
1223 0 : ierr=ierr+1
1224 0 : rhogg(ig,igp)=czero
1225 : end if
1226 : end do
1227 : end do
1228 :
1229 24 : if (ierr /= 0) then
1230 : write(msg,'(a,i0,1x,3a)')&
1231 0 : 'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1232 0 : 'Enlarge the FFT mesh to get rid of this problem. '
1233 0 : ABI_WARNING(msg)
1234 : end if
1235 :
1236 20364 : rhogg=four_pi*rhogg
1237 24 : ABI_FREE(rhog_dp)
1238 24 : ABI_FREE(rhog)
1239 :
1240 : ! Calculate GPP parameters
1241 : ! unsymmetrized epsm1 -> epsm1=|q+Gp|/|q+G|*epsm1
1242 72 : ABI_MALLOC(qplusg,(npwc))
1243 72 : ABI_MALLOC(temp,(npwc,npwc))
1244 72 : ABI_MALLOC_OR_DIE(omegatwsq,(npwc,npwc), ierr)
1245 :
1246 20388 : temp = -epsm1(:,:)
1247 : !
1248 : ! RS still not obvious for me whether one shall use the symmetrized inverse DM or the unsymmetrized one
1249 : ! the default here is to use the symmetrized one, I must discuss this with XG
1250 : !
1251 : ! MG it turns out that using the symmetrized inverse DM in the plasmon-pole
1252 : ! equations give the same results for the squared plasmon frequencies omegatwsq while the
1253 : ! squared bare plasma frequencies bigomegatwsq related to the symmetrized dielectric matrix
1254 : ! are obtained multiplying by |q+G1|/|q+G2|.
1255 : !
1256 : if (.not.use_symmetrized) then
1257 : qlist(:,1) = qpt
1258 : call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1259 : do ig=1,npwc
1260 : do igp=1,npwc
1261 : temp(ig,igp)=qplusg(igp)/qplusg(ig)*temp(ig,igp)
1262 : end do
1263 : end do
1264 : end if
1265 :
1266 24 : nimwp=0
1267 708 : do ig=1,npwc
1268 684 : temp(ig,ig)=temp(ig,ig)+one
1269 20364 : do igp=1,npwc
1270 19656 : bigomegatwsq(ig,igp) = rhogg(ig,igp)*qratio(ig,igp)
1271 19656 : omegatwsq(ig,igp)=bigomegatwsq(ig,igp)/temp(ig,igp)
1272 : !
1273 : ! Set to an arbitrary value the omegawsq which become negative or imaginary
1274 : ! in principle these correspond to cases where the imaginary part of epsm1 does not have
1275 : ! a well defined peak. The imaginary part of epsm1 in these cases oscillates with a small amplitude
1276 : ! since the amplitude A_GGpr=-pi/2*bigomegatwsq/omegatw,
1277 : ! it follows that bigomegatwsq shall be set to zero for these cases
1278 20340 : if ( REAL(omegatwsq(ig,igp))<= tol12 .or. AIMAG(omegatwsq(ig,igp))**2*tol12> REAL(omegatwsq(ig,igp))**2) then
1279 10280 : nimwp=nimwp+1
1280 :
1281 10280 : if ( invalid_freq == 1 ) then
1282 : ! set omegatwsq to 1 hartree
1283 0 : omegatwsq(ig,igp)=cone
1284 0 : AA = epsm1(ig,igp)
1285 0 : if ( ig == igp ) AA = AA - one
1286 0 : omegatw(ig,igp)=SQRT(REAL(omegatwsq(ig,igp)))
1287 0 : bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1288 10280 : elseif ( invalid_freq == 2 ) then
1289 : ! set omegatwsq to infinity
1290 3911 : omegatwsq(ig,igp)=cone/tol6
1291 3911 : AA = epsm1(ig,igp)
1292 3911 : if ( ig == igp ) AA = AA - one
1293 3911 : omegatw(ig,igp)=SQRT(REAL(omegatwsq(ig,igp)))
1294 3911 : bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1295 : else
1296 : ! simply ignore all cases of omegatw with imaginary values
1297 6369 : bigomegatwsq(ig,igp)=(0.,0.)
1298 6369 : omegatw(ig,igp)=(ten,0.)
1299 : end if
1300 : if (check_imppf) then
1301 : write(msg,'(a,2(i0,1x))')' Imaginary plasmon frequency at : ',ig,igp
1302 : call wrtout(std_out,msg)
1303 : end if
1304 : else
1305 : ! this part has been added to deal with systems without inversion symmetry
1306 : ! this new implementation gives the same results as the previous one if
1307 : ! omegatwsq is a pure real number and has the advantage of being an improved
1308 : ! approach for systems without an inversion center.
1309 9376 : lambda=ABS(omegatwsq(ig,igp))
1310 9376 : phi=ATAN(AIMAG(omegatwsq(ig,igp))/REAL(omegatwsq(ig,igp)))
1311 9376 : omegatw(ig,igp)=SQRT(lambda/COS(phi))
1312 9376 : bigomegatwsq(ig,igp)=bigomegatwsq(ig,igp)*(1.-(0.,1.)*TAN(phi))
1313 : ! Uncomment the following line and comment the previous to restore the old version.
1314 : !omegatw(ig,igp)=sqrt(real(omegatwsq(ig,igp)))
1315 : end if
1316 : end do
1317 : end do
1318 :
1319 24 : write(msg,'(3a,i0,a,i0)')' At q-point : ',trim(ktoa(qpt)), ' # imaginary plasmonpole frequencies: ',nimwp,' / ',npwc**2
1320 24 : call wrtout(std_out, msg)
1321 : write(msg,'(a,f12.8,a,3(i0,1x))') &
1322 40752 : " omega twiddle minval: ", MINVAL(ABS(omegatw))*Ha_eV, "[eV], min location: ",MINLOC(ABS(omegatw))
1323 24 : call wrtout(std_out, msg)
1324 :
1325 24 : call destroy_mpi_enreg(MPI_enreg_seq)
1326 :
1327 24 : ABI_FREE(omegatwsq)
1328 24 : ABI_FREE(rhogg)
1329 24 : ABI_FREE(temp)
1330 24 : ABI_FREE(qplusg)
1331 24 : ABI_FREE(qratio)
1332 :
1333 24 : end subroutine cppm2par
1334 : !!***
1335 :
1336 : !----------------------------------------------------------------------
1337 :
1338 : !!****f* m_ppmodel/cppm3par
1339 : !! NAME
1340 : !! cppm3par
1341 : !!
1342 : !! FUNCTION
1343 : !! Calculate the plasmon-pole parameters using the von Linden-Horsh model (PRB 37, 8351, 1988) [[cite:vonderLinden1988]]
1344 : !! (see also Pag 22 of Quasiparticle Calculations in Solids [[cite:Aulbur2001]].
1345 : !!
1346 : !! INPUTS
1347 : !! epsm1(npwc,npwc))= symmetrized inverse dielectric
1348 : !! ngfftf(18)=contain all needed information about 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
1349 : !! npwc=number of plane waves in epsm1
1350 : !! qratio=(q+G1).(q+G2)/(|q+G1|.|q+G2|)
1351 : !! rhor(nfftf)=charge density on the real space FFT grid
1352 : !! nfftf=number of points in the FFT grid (for this processor)
1353 : !! gvec(3,npwc)= G vectors in reduced coordinates
1354 : !!
1355 : !! OUTPUT
1356 : !! omegatw(npwc,npwc)= plasmon pole positions
1357 : !! bigomegatwsq(npwc,npwc)=(E_{q,ii}^{-1}-1)*omegatw
1358 : !! where E^{-1} is the eigenvalue of the inverse dielectric matrix
1359 : !! eigtot(npwc,npwc)=the eigvectors of the symmetrized inverse dielectric matrix
1360 : !! (first index for G, second index for bands)
1361 : !!
1362 : !! SOURCE
1363 :
1364 18 : subroutine cppm3par(qpt,npwc,epsm1,ngfftf,gvec,gprimd,rhor,nfftf,bigomegatwsq,omegatw,eigtot)
1365 :
1366 : !Arguments ------------------------------------
1367 : !scalars
1368 : integer,intent(in) :: nfftf,npwc
1369 : !arrays
1370 : integer,intent(in) :: gvec(3,npwc),ngfftf(18)
1371 : real(dp),intent(in) :: qpt(3),gprimd(3,3),rhor(nfftf)
1372 : complex(gwp),intent(in) :: epsm1(npwc,npwc)
1373 : complex(gwp),intent(out) :: bigomegatwsq(npwc,1),omegatw(npwc) ,eigtot(npwc,npwc)
1374 :
1375 : !Local variables-------------------------------
1376 : !TODO these should be dp
1377 : !scalars
1378 : integer :: idx,ierr,ig,igp,ii,jj,ngfft1,ngfft2,ngfft3,gmgp_idx
1379 : real(dp) :: num,qpg_dot_qpgp
1380 : complex(dp) :: conjg_eig
1381 : logical :: qiszero
1382 : character(len=500) :: msg
1383 18 : type(MPI_type) :: MPI_enreg_seq
1384 : !arrays
1385 : real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),qlist(3,1)
1386 18 : real(dp),allocatable :: eigval(:),qplusg(:),rhog_dp(:,:),zhpev2(:),tmp_rhor(:)
1387 18 : complex(dp),allocatable :: eigvec(:,:),matr(:),mm(:,:),rhog(:),rhogg(:,:), zhpev1(:),zz(:)
1388 : !*************************************************************************
1389 :
1390 : ! Fake MPI_type for the sequential part.
1391 18 : call initmpi_seq(MPI_enreg_seq)
1392 18 : call MPI_enreg_seq%distribfft%init_seq('c',ngfftf(2),ngfftf(3),'all')
1393 :
1394 30 : qiszero = (ALL(ABS(qpt)<1.0e-3))
1395 :
1396 180 : b1 = two_pi*gprimd(:,1); b2 = two_pi*gprimd(:,2); b3 = two_pi*gprimd(:,3)
1397 :
1398 18 : ngfft1=ngfftf(1); ngfft2=ngfftf(2); ngfft3=ngfftf(3)
1399 :
1400 54 : ABI_MALLOC(rhog_dp,(2,nfftf))
1401 54 : ABI_MALLOC(rhog,(nfftf))
1402 72 : ABI_MALLOC_OR_DIE(rhogg,(npwc, npwc), ierr)
1403 : !
1404 : ! === Compute the density in G space rhog(r)--> rho(G) ===
1405 : ! FIXME this has to be fixed, rho(G) should be passed instead of doing FFT for each q
1406 :
1407 54 : ABI_MALLOC(tmp_rhor,(nfftf))
1408 65112 : tmp_rhor=rhor ! To avoid having to use intent(inout).
1409 18 : call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1410 18 : ABI_FREE(tmp_rhor)
1411 :
1412 65094 : rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1413 : !
1414 : ! Calculate the FFT index of each (G-Gp) vector and assign the value
1415 : ! of the correspondent density simultaneously
1416 18 : ierr=0
1417 504 : do ig=1,npwc
1418 13626 : do igp=1,npwc
1419 52488 : gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1420 13608 : if (gmgp_idx/=0) then
1421 13122 : rhogg(ig,igp)=rhog(gmgp_idx)
1422 : else
1423 0 : ierr=ierr+1
1424 0 : rhogg(ig,igp)=czero
1425 : end if
1426 : end do
1427 : end do
1428 :
1429 18 : if (ierr /= 0) then
1430 : write(msg,'(a,i0,3a)')&
1431 0 : 'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1432 0 : 'Enlarge the FFT mesh to get rid of this problem. '
1433 0 : ABI_WARNING(msg)
1434 : end if
1435 :
1436 : ! mm(G,Gp) = (q+G) \cdot (q+Gp) n(G-Gp)
1437 54 : ABI_MALLOC_OR_DIE(mm, (npwc,npwc), ierr)
1438 :
1439 504 : do ig=1,npwc
1440 486 : if (qiszero) then
1441 : ! To be discussed with Riad, here we should use the small q
1442 : ! to be consistent and consider the limit q-->0
1443 324 : gpq(:)=gvec(:,ig)
1444 : else
1445 1620 : gpq(:)=gvec(:,ig)+qpt
1446 : end if
1447 13626 : do igp=1,npwc
1448 13122 : if (qiszero) then
1449 8748 : gppq(:)=gvec(:,igp)
1450 : else
1451 43740 : gppq(:)=gvec(:,igp)+qpt
1452 : end if
1453 13122 : qpg_dot_qpgp=zero
1454 52488 : do ii=1,3
1455 : qpg_dot_qpgp=qpg_dot_qpgp+&
1456 : ( gpq(1)*b1(ii) +gpq(2)*b2(ii) +gpq(3)*b3(ii))*&
1457 52488 : (gppq(1)*b1(ii)+gppq(2)*b2(ii)+gppq(3)*b3(ii))
1458 : end do
1459 13608 : mm(ig,igp)=rhogg(ig,igp)*qpg_dot_qpgp
1460 : end do !igp
1461 : end do !ig
1462 :
1463 18 : ABI_FREE(rhog_dp)
1464 18 : ABI_FREE(rhog)
1465 : ! === Now we have rhogg,rho0 ===
1466 : !
1467 : ! Calculate the dielectric matrix eigenvalues and vectors
1468 : ! Use only the static epsm1 i.e., only the w=0 part (eps(:,:,1,:))
1469 54 : ABI_MALLOC(eigval,(npwc))
1470 54 : ABI_MALLOC_OR_DIE(eigvec, (npwc, npwc), ierr)
1471 :
1472 54 : ABI_MALLOC(zz,(npwc))
1473 504 : zz=czero
1474 :
1475 36 : ABI_MALLOC(qplusg,(npwc))
1476 :
1477 : ! Store the susceptibility matrix in upper mode before calling zhpev.
1478 54 : ABI_MALLOC_OR_DIE(matr,(npwc*(npwc+1)/2), ierr)
1479 :
1480 : idx=1
1481 504 : do ii=1,npwc
1482 7308 : do jj=1,ii
1483 7290 : matr(idx)=epsm1(jj,ii); idx=idx+1
1484 : end do
1485 : end do
1486 :
1487 54 : ABI_MALLOC(zhpev2,(3*npwc-2))
1488 54 : ABI_MALLOC(zhpev1,(2*npwc-1))
1489 :
1490 18 : call ZHPEV('V','U',npwc,matr,eigval,eigvec,npwc,zhpev1,zhpev2,ierr)
1491 18 : ABI_FREE(matr)
1492 18 : ABI_FREE(zhpev2)
1493 18 : ABI_FREE(zhpev1)
1494 :
1495 18 : if (ierr < 0) then
1496 : write (msg,'(2a,i0,a)')&
1497 0 : ' Failed to calculate the eigenvalues and eigenvectors of the dielectric matrix ',ch10,&
1498 0 : ierr*(-1),'-th argument in the matrix has an illegal value. '
1499 0 : ABI_ERROR(msg)
1500 : end if
1501 :
1502 18 : if (ierr > 0) then
1503 : write(msg,'(3a,i0,2a)')&
1504 0 : ' Failed to calculate the eigenvalues and eigenvectors of the dielectric matrix ',ch10,&
1505 0 : ' the algorithm failed to converge; ierr = ', ierr,ch10,&
1506 0 : ' off-diagonal elements of an intermediate tridiagonal form did not converge to zero. '
1507 0 : ABI_ERROR(msg)
1508 : end if
1509 :
1510 : ! Calculate the PPM parameters and the eigenpotentials needed for
1511 : ! the calculation of the generalized overlap matrix
1512 : ! Note: the eigenpotentials has to be calculated on the FFT (G-Gp) index
1513 : !
1514 : ! Save eigenvectors of \tilde\epsilon^{-1}
1515 : ! MG well it is better to save \Theta otherwise
1516 : ! we have to calculare \Theta for each band, spin, k-point but oh well
1517 13626 : eigtot=eigvec
1518 :
1519 18 : qlist(:,1) = qpt
1520 18 : call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1521 : !
1522 : ! Basic Equation:
1523 : !
1524 : ! \Theta_{q,ii}(G)=\Psi_{q,ii}(G)/|q+G|
1525 : ! where \Psi_{q,ii}(G) is the eigenvector of \tilde\epsilon^{-1}
1526 :
1527 : ! \tilde\omega_{ii,q}^2= 4\pi (1-eigenval(ii,q)))
1528 : ! \sum_{G,Gp} \Theta^*_{q,ii}(G) (q+G)\cdot(q+Gp) n(G-Gp) \Theta_{q,ii}(Gp)
1529 :
1530 504 : do ii=1,npwc !DM band
1531 : ! Calculate \Theta_{q,ii}(G)
1532 : ! why the first element is not modified? if the problem is the small value of qplusg(1)
1533 : ! we could multiply by sqrt(mod((q+G)(q+G'))) and then add the sing at the end
1534 486 : if (qiszero)then
1535 2187 : eigvec(2:,ii)=eigvec(2:,ii)/qplusg(2:)
1536 : else
1537 11340 : eigvec(:,ii)=eigvec(:,ii)/qplusg(:)
1538 : end if
1539 13608 : do ig=1,npwc
1540 13122 : conjg_eig=CONJG(eigvec(ig,ii))
1541 367902 : do igp=1,npwc
1542 367416 : if(qiszero .and. ig==1 .and. igp==1)then
1543 81 : zz(ii)=zz(ii)+conjg_eig*rhogg(ig,igp)*eigvec(igp,ii)
1544 : else
1545 354213 : zz(ii)=zz(ii)+conjg_eig*mm(ig,igp)*eigvec(igp,ii)
1546 : end if
1547 : end do
1548 : end do
1549 :
1550 486 : num=one-eigval(ii)
1551 486 : if (num<=zero) then
1552 : ! here I think we should set bigomegatwsq=0 and omegatw to an arbitrary value
1553 : ! maybe we can output a warning TO BE discussed with Riad
1554 0 : if (ABS(num)<1.0d-4) then
1555 : num=1.0d-5
1556 : else
1557 0 : ABI_ERROR("One or more imaginary plasmon pole energies")
1558 : end if
1559 : end if
1560 :
1561 486 : omegatw(ii)=SQRT(4*pi*REAL(zz(ii))/num)
1562 : ! this should be \alpha = 2\pi omegatw * (1-eigenval)
1563 : ! MG check this, in the review I found a factor 2\pi, maybe it is reintroduced later
1564 504 : bigomegatwsq(ii,1)=num*omegatw(ii)
1565 : end do
1566 :
1567 18 : ABI_FREE(rhogg)
1568 18 : ABI_FREE(mm)
1569 18 : ABI_FREE(eigval)
1570 18 : ABI_FREE(zz)
1571 18 : ABI_FREE(eigvec)
1572 18 : ABI_FREE(qplusg)
1573 :
1574 18 : call destroy_mpi_enreg(MPI_enreg_seq)
1575 :
1576 18 : write(msg,'(2a,f12.8,2a,3i5)')ch10,&
1577 522 : ' cppm3par : omega twiddle minval [eV] = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1578 540 : ' omega twiddle min location = ',MINLOC(ABS(omegatw))
1579 18 : call wrtout(std_out,msg)
1580 :
1581 18 : end subroutine cppm3par
1582 : !!***
1583 :
1584 : !----------------------------------------------------------------------
1585 :
1586 : !!****f* m_ppmodel/cppm4par
1587 : !! NAME
1588 : !! cppm4par
1589 : !!
1590 : !! FUNCTION
1591 : !! Calculate the plasmon-pole parameters using Engel-Farid model (PRB47,15931,1993) [[cite:Engel1993]].
1592 : !! See also Quasiparticle Calculations in Solids [[cite:Aulbur2001]] page. 23.
1593 : !!
1594 : !! INPUTS
1595 : !! qpt(3)=Reduced coordinates of the q-point.
1596 : !! npwc=number of plane waves in epsm1
1597 : !! epsm1(npwc,npwc)=symmetrized inverse dielectric matrix.
1598 : !! ngfftf(18)=contain all needed information about 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
1599 : !! gvec(3,npwc)=G vectors in reduced coordinated
1600 : !! gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
1601 : !! rhor(nfftf)=charge density on the real space FFT grid
1602 : !! nfftf=Number of FFT points.
1603 : !!
1604 : !! OUTPUT
1605 : !! bigomegatwsq(npwc,npwc)=plasmon-pole strength.
1606 : !! omegatw(npwc)=plasmon-pole frequencies.
1607 : !!
1608 : !! SOURCE
1609 :
1610 18 : subroutine cppm4par(qpt, npwc, epsm1, ngfftf, gvec, gprimd, rhor, nfftf, bigomegatwsq, omegatw)
1611 :
1612 : !Arguments ------------------------------------
1613 : !scalars
1614 : integer,intent(in) :: nfftf,npwc
1615 : !arrays
1616 : integer,intent(in) :: gvec(3,npwc),ngfftf(18)
1617 : real(dp),intent(in) :: gprimd(3,3),qpt(3), rhor(nfftf)
1618 : complex(gwp),intent(in) :: epsm1(npwc,npwc)
1619 : complex(gwp),intent(out) :: bigomegatwsq(npwc,npwc),omegatw(npwc)
1620 :
1621 : !Local variables-------------------------------
1622 : !scalars
1623 : integer :: ierr,ig,igp,ii,ngfft1,ngfft2,ngfft3,gmgp_idx
1624 : real(dp) :: qpg_dot_qpgp
1625 : character(len=500) :: msg
1626 : character(len=80) :: bar
1627 18 : type(MPI_type) :: MPI_enreg_seq
1628 : !arrays
1629 : real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),qlist(3,1)
1630 18 : real(dp),allocatable :: eigval(:),qplusg(:),rhog_dp(:,:),tmp_rhor(:)
1631 18 : complex(dp),allocatable :: chi(:,:), mm(:,:),mtemp(:,:),rhog(:), tmp1(:),zz2(:,:)
1632 : !*************************************************************************
1633 :
1634 : ! Calculate density in G space rhog(G)
1635 : ! FIXME this has to be fixed, rho(G) should be passed instead of doing FFT for each q
1636 18 : call initmpi_seq(MPI_enreg_seq)
1637 18 : call MPI_enreg_seq%distribfft%init_seq('c',ngfftf(2),ngfftf(3),'all')
1638 :
1639 54 : ABI_MALLOC(rhog_dp, (2,nfftf))
1640 :
1641 : ! Conduct FFT tho(r)-->rhog(G)
1642 54 : ABI_MALLOC(tmp_rhor,(nfftf))
1643 65112 : tmp_rhor = rhor ! To avoid having to use intent(inout).
1644 18 : call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1645 :
1646 18 : ABI_FREE(tmp_rhor)
1647 18 : call destroy_mpi_enreg(MPI_enreg_seq)
1648 :
1649 54 : ABI_MALLOC(rhog, (nfftf))
1650 65094 : rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1651 18 : ABI_FREE(rhog_dp)
1652 :
1653 : ! Calculate the FFT index of each (G-Gp) vector and assign the value
1654 : ! of the correspondent density simultaneously
1655 18 : ngfft1=ngfftf(1)
1656 18 : ngfft2=ngfftf(2)
1657 18 : ngfft3=ngfftf(3)
1658 :
1659 72 : ABI_MALLOC_OR_DIE(mm, (npwc,npwc), ierr)
1660 :
1661 18 : ierr = 0
1662 504 : do ig=1,npwc
1663 13626 : do igp=1,npwc
1664 52488 : gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1665 13608 : if (gmgp_idx /= 0) then
1666 13122 : mm(ig,igp) = rhog(gmgp_idx)
1667 : else
1668 0 : ierr = ierr + 1
1669 0 : mm(ig,igp) = czero
1670 : end if
1671 : end do
1672 : end do
1673 :
1674 18 : if (ierr /= 0) then
1675 : write(msg,'(a,i0,3a)')&
1676 0 : 'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1677 0 : 'Enlarge the FFT mesh to get rid of this problem. '
1678 0 : ABI_WARNING(msg)
1679 : end if
1680 :
1681 18 : ABI_FREE(rhog)
1682 :
1683 : ! Now we have rhogg, calculate the M matrix (q+G1).(q+G2) n(G1-G2)
1684 180 : b1=two_pi*gprimd(:,1); b2=two_pi*gprimd(:,2); b3=two_pi*gprimd(:,3)
1685 504 : do ig=1,npwc
1686 1944 : gpq(:)=gvec(:,ig)+qpt
1687 13626 : do igp=1,npwc
1688 52488 : gppq(:)=gvec(:,igp)+qpt
1689 : qpg_dot_qpgp=zero
1690 52488 : do ii=1,3
1691 : qpg_dot_qpgp = qpg_dot_qpgp + &
1692 : ( gpq(1)*b1(ii) +gpq(2)*b2(ii) +gpq(3)*b3(ii))*&
1693 52488 : (gppq(1)*b1(ii)+gppq(2)*b2(ii)+gppq(3)*b3(ii))
1694 : end do
1695 13608 : mm(ig,igp) = mm(ig,igp)*qpg_dot_qpgp
1696 : end do ! igp
1697 : end do ! ig
1698 :
1699 : ! Extract the reducible polarizability chi: e^{-1} = 1 + v chi
1700 : ! \tilde\epsilon^{-1}_{G1 G2} = \delta_{G1 G2} + 4\pi \frac{\chi_{G1 G2}}{|q+G1| |q+G2|}
1701 : !MG TODO too much memory in chi, we can do all this stuff inside a loop
1702 54 : ABI_MALLOC_OR_DIE(chi, (npwc,npwc), ierr)
1703 54 : ABI_MALLOC(qplusg, (npwc))
1704 :
1705 13626 : chi(:,:)=epsm1(:,:)
1706 18 : qlist(:,1) = qpt
1707 18 : call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1708 :
1709 504 : do ig=1,npwc
1710 504 : chi(ig,ig)=chi(ig,ig) - one
1711 : end do
1712 :
1713 504 : do ig=1,npwc
1714 13626 : do igp=1,npwc
1715 13608 : chi(ig,igp) = chi(ig,igp) * qplusg(ig) * qplusg(igp) / four_pi
1716 : end do
1717 : end do
1718 :
1719 : ! Solve chi(w=)*X = Lambda M*X where Lambda=-1/em(q)**2
1720 36 : ABI_MALLOC(eigval, (npwc))
1721 54 : ABI_MALLOC_OR_DIE(mtemp, (npwc,npwc), ierr)
1722 :
1723 : ! Copy mm into working array as xhegv changes input matrices
1724 13626 : mtemp(:,:) = mm(:,:)
1725 :
1726 18 : call xhegv(1,"Vectors","Upper",npwc,chi,mtemp,eigval)
1727 18 : ABI_FREE(mtemp)
1728 :
1729 : ! Now chi contains the eigenvectors.
1730 : ! Eigenvectors are normalized as: X_i^* M X_j = \delta_{ij}
1731 :
1732 : ! Calculate the plasmon pole parameters
1733 : ! good check: the lowest plasmon energy on gamma should be
1734 : ! close to experimental plasma energy within an error of 10%
1735 : ! this error can be reduced further if one includes the non local
1736 : ! commutators in the calculation of the polarizability at q==0
1737 :
1738 54 : ABI_MALLOC(tmp1,(npwc))
1739 54 : ABI_MALLOC_OR_DIE(zz2, (npwc, npwc), ierr)
1740 13626 : zz2(:,:)= zero
1741 :
1742 : ! Caller is responsible for handing small q case
1743 18 : qlist(:,1) = qpt
1744 18 : call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg)
1745 :
1746 504 : do ii=1,npwc
1747 : ! keeping in mind that the above matrix is negative definite
1748 : ! we might have a small problem with the eigvals corresponding to large G vectors
1749 : ! i.e. DM band index, where the eigevalues become very small with
1750 : ! possibility of being small positive numbers (due to numerical problems)
1751 : ! thus as a caution one can use the following condition
1752 : ! this will not affect the result since such a huge plasmon energy give almost zero
1753 : ! contribution to the self-energy correlation energy.
1754 :
1755 486 : if (eigval(ii)>=zero) then
1756 : !write(msg,'(a,i0,a,es16.6)')' Imaginary plasmon pole eigenenergy, eigenvector number ',ii,' with eigval',eigval(ii),ch10
1757 : !ABI_ERROR(msg)
1758 0 : eigval(ii) = -1.0d-4
1759 : end if
1760 :
1761 : ! Save plasmon energies omega_p(q)
1762 486 : omegatw(ii) = SQRT(-one/eigval(ii))
1763 :
1764 : ! Calculate and save scaled plasmon-pole eigenvectors
1765 : ! defined as \sqrt{4\pi} \frac{Mx}{\sqrt{\tilde\omega} |q+G|}
1766 13608 : tmp1(:)=chi(:,ii)
1767 :
1768 13626 : do ig=1,npwc
1769 367416 : do igp=1,npwc
1770 367416 : zz2(ig,ii)=zz2(ig,ii)+mm(ig,igp)*tmp1(igp) ! z --> y
1771 : end do
1772 13608 : bigomegatwsq(ig,ii)= SQRT(four_pi) * zz2(ig,ii) / SQRT(omegatw(ii)) / qplusg(ig)
1773 : end do
1774 :
1775 : end do ! ii
1776 :
1777 18 : ABI_FREE(tmp1)
1778 18 : ABI_FREE(eigval)
1779 18 : ABI_FREE(zz2)
1780 18 : ABI_FREE(qplusg)
1781 18 : ABI_FREE(chi)
1782 18 : ABI_FREE(mm)
1783 :
1784 18 : bar = repeat('-', 80)
1785 18 : write(msg,'(3a)')bar,ch10,' plasmon energies in eV vs q vector shown for the lowest 10 bands'
1786 18 : call wrtout(std_out,msg)
1787 198 : write(msg,'(2x,5x,10f7.3)')(REAL(omegatw(ig))*Ha_eV, ig=1,min(10, npwc))
1788 18 : call wrtout(std_out,msg)
1789 18 : write(msg,'(a)')bar
1790 18 : call wrtout(std_out,msg)
1791 :
1792 18 : write(msg,'(2a,f12.8,2a,3i5)')ch10,&
1793 522 : ' cppm4par: omega twiddle minval [eV] = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1794 540 : ' omega twiddle min location = ',MINLOC(ABS(omegatw))
1795 18 : call wrtout(std_out,msg)
1796 :
1797 18 : end subroutine cppm4par
1798 : !!***
1799 :
1800 : !----------------------------------------------------------------------
1801 :
1802 : !!****f* m_ppmodel/cqratio
1803 : !! NAME
1804 : !! cqratio
1805 : !!
1806 : !! FUNCTION
1807 : !! Calculate qratio(G,Gp,q)= (q+G)\cdot(q+Gp) / |q+G|^2 needed for Hybertsen-Louie and Plasmonpole model
1808 : !!
1809 : !! INPUTS
1810 : !! npwc=number of planewaves considered (used for the correlation part)
1811 : !! gvec(3,npwc)=reduced coordinates of the plane waves
1812 : !! q(3)=coordinates of q points
1813 : !! gmet(3,3)=metric in reciprocal space
1814 : !! gprimd(3,3)=reciprocal lattice vectors
1815 : !!
1816 : !! OUTPUT
1817 : !! qratio(npwc,npwc)=(q+G).(q+Gp)
1818 : !!
1819 : !! SOURCE
1820 :
1821 24 : subroutine cqratio(npwc, gvec, q, gmet, gprimd, qratio)
1822 :
1823 : !Arguments ------------------------------------
1824 : !scalars
1825 : integer,intent(in) :: npwc
1826 : !arrays
1827 : integer,intent(in) :: gvec(3,npwc)
1828 : real(dp),intent(in) :: gmet(3,3),gprimd(3,3),q(3)
1829 : real(dp),intent(out) :: qratio(npwc,npwc)
1830 :
1831 : !Local variables ------------------------------
1832 : !scalars
1833 : integer :: ig,igp,ii
1834 : real(dp),parameter :: tol = 0.001_dp
1835 : real(dp) :: qpg_dot_qpgp
1836 : !arrays
1837 24 : real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),norm(npwc)
1838 : !************************************************************************
1839 :
1840 240 : b1=two_pi*gprimd(:,1); b2=two_pi*gprimd(:,2); b3=two_pi*gprimd(:,3)
1841 :
1842 21048 : norm(:)=zero; qratio=zero
1843 :
1844 : !FIXME this loops have to be rewritten!!!!
1845 708 : do ig=1,npwc
1846 2736 : gpq(:)=gvec(:,ig)+q
1847 10968 : norm(ig)=two_pi*SQRT(DOT_PRODUCT(gpq,MATMUL(gmet,gpq)))
1848 : !norm(ig)=normv(gpq,gmet,'g')
1849 : end do
1850 :
1851 708 : do ig=1,npwc
1852 2736 : gpq(:)=gvec(:,ig)+q
1853 20364 : do igp=1,npwc
1854 78624 : gppq(:)=gvec(:,igp)+q
1855 : qpg_dot_qpgp=zero
1856 : !qpg_dot_qpgp=vdotw(gpq,gppq,gmet,'g')
1857 78624 : do ii=1,3
1858 : qpg_dot_qpgp=qpg_dot_qpgp+&
1859 : ( gpq(1)*b1(ii) + gpq(2)*b2(ii) + gpq(3)*b3(ii))*&
1860 78624 : (gppq(1)*b1(ii) + gppq(2)*b2(ii) +gppq(3)*b3(ii))
1861 : end do
1862 :
1863 : ! Now calculate qratio = (q+G).(q+Gp)/|q+G|^2
1864 : ! when |q+G|^2 and (q+G).(q+Gp) are both zero set (q+G).(q+Gp)/|q+G|^2 = 1
1865 : ! when |q+G|^2 is zero and |q+Gp| is not zero set (q+G).(q+Gp)/|q+G|^2 = 0
1866 20340 : if (norm(ig) < tol) then
1867 114 : if (norm(igp) < tol) then ! Case q=0 and G=Gp=0
1868 4 : qratio(ig,igp) = one
1869 : else ! Case q=0 and G=0 and Gp !=0
1870 110 : qratio(ig,igp) = zero
1871 : end if
1872 19542 : else if (norm(igp) < tol) then ! Case q=0 and G= !0 and Gp=0
1873 110 : qratio(ig,igp)=zero
1874 : else
1875 19432 : qratio(ig,igp)=qpg_dot_qpgp / norm(ig)**2
1876 : end if
1877 :
1878 : end do
1879 : end do
1880 :
1881 24 : end subroutine cqratio
1882 : !!***
1883 :
1884 : !----------------------------------------------------------------------
1885 :
1886 : !!****f* m_ppmodel/ppm_calc_sigc
1887 : !!
1888 : !! NAME
1889 : !! ppm_calc_sigc
1890 : !!
1891 : !! FUNCTION
1892 : !! Calculate the contribution to self-energy operator for a single band s in the band sum
1893 : !! using a plasmon-pole model.
1894 : !!
1895 : !! INPUTS
1896 : !! nspinor=Number of spinor components.
1897 : !! npwc=Number of G vectors in the plasmon pole (correlation part)
1898 : !! nomega=Number of frequencies.
1899 : !! rhotwgp(npwx)=oscillator matrix elements divided by |q+G| i.e. $\frac{\langle b1 k-q s | e^{-i(q+G)r | b2 k s \rangle}{|q+G|}$.
1900 : !! botsq(npwc,dm2_botsq)=Plasmon pole parameters for this q-point.
1901 : !! otq(npwc,dm2_otq)=Plasmon pole parameters for this q-point.
1902 : !! omegame0i(nomega)=($\omega$ - $\epsilon_i)$
1903 : !! zcut=Small imaginary part to avoid the divergence. (see related input variable)
1904 : !! theta_mu_minus_e0i= $\theta(\mu-\epsilon_{k-q,b1,s}), defines if the state is occupied or not.
1905 : !! eig(dm_eig,dm_eig)=The eigvectors of the symmetrized inverse dielectric matrix for this q point
1906 : !! (first index for G, second index for bands).
1907 : !! npwx=number of G vectors in rhotwgp.
1908 : !!
1909 : !! OUTPUT
1910 : !! ket(npwc,nomega):
1911 : !!
1912 : !! === model==1,2 ====
1913 : !!
1914 : !! ket(G,omega) += Sum_G2 Omega(G,G2) * rhotw(G2)
1915 : !! ---------------------------------------------------
1916 : !! 2 omegatw(G,G2) (omega - E_i + omegatw(G,G2)(2f-1))
1917 : !!
1918 : !! sigcme(nomega) (to be described), only relevant if ppm3 or ppm4
1919 : !!
1920 : !! NOTES
1921 : !! The i/two_pi factor in the convolution between G and W is included in this routine.
1922 : !!
1923 : !! TODO:
1924 : !! Use BLAS for better efficiency
1925 : !!
1926 : !! SOURCE
1927 :
1928 1557834 : subroutine ppm_calc_sigc(ppm, nspinor, npwc, nomega, rhotwgp, botsq, otq, &
1929 1557834 : omegame0i, zcut, theta_mu_minus_e0i, eig, npwx, ket, sigcme)
1930 :
1931 : !Arguments ------------------------------------
1932 : !scalars
1933 : class(ppmodel_t),intent(in) :: ppm
1934 : integer,intent(in) :: nomega, npwc, npwx, nspinor
1935 : real(dp),intent(in) :: theta_mu_minus_e0i, zcut
1936 : !arrays
1937 : real(dp),intent(in) :: omegame0i(nomega)
1938 : complex(gwp),intent(in) :: botsq(npwc, ppm%dm2_botsq), eig(ppm%dm_eig, ppm%dm_eig), otq(npwc, ppm%dm2_otq)
1939 : complex(gwp),intent(in) :: rhotwgp(npwx, nspinor)
1940 : complex(gwp),intent(inout) :: ket(npwc, nspinor, nomega)
1941 : complex(gwp),intent(out) :: sigcme(nomega)
1942 :
1943 : !Local variables-------------------------------
1944 : !scalars
1945 : integer :: ig,igp,ii,iw,ispinor
1946 : real(dp),parameter :: tol_occ = tol3, tol_omega = tol6
1947 : real(dp) :: den, den2, ff, inv_den, omegame0i_io, otw, twofm1, twofm1_zcut, twofm1_zcut2, zcut2
1948 : complex(gwp) :: ct, num, numf, rhotwgdp_igp
1949 : logical :: fully_occupied, totally_empty
1950 : !character(len=500) :: msg
1951 : !arrays
1952 1557834 : complex(gwp),allocatable :: rhotwgdpcc(:)
1953 : !*************************************************************************
1954 :
1955 1557834 : zcut2 = zcut ** 2
1956 :
1957 3111828 : select case (ppm%model)
1958 :
1959 : case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
1960 1553994 : fully_occupied = (abs(theta_mu_minus_e0i-one) < tol_occ)
1961 1553994 : totally_empty = (abs(theta_mu_minus_e0i ) < tol_occ)
1962 :
1963 3114708 : do ispinor=1,nspinor
1964 :
1965 1560714 : if (.not. totally_empty) then
1966 : ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(\mu-e_s) / (\omega+\omegat_{G1G2}-e_s-i\delta)
1967 4432550 : twofm1_zcut = zcut
1968 4432550 : twofm1_zcut2 = zcut2
1969 : !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den, den2)
1970 4432550 : do iw=1,nomega
1971 3911815 : omegame0i_io = omegame0i(iw)
1972 : !if (iw > 1 .and. abs(omegame0i(iw) - omegame0i(iw-1)) < tol_omega) then
1973 : ! ket(:,:,iw) = ket(:,:,iw-1); cycle
1974 : !end if
1975 :
1976 96885963 : do igp=1,npwc
1977 92453413 : rhotwgdp_igp = rhotwgp(igp, ispinor)
1978 4832128747 : do ig=1,npwc
1979 4735763519 : otw = DBLE(otq(ig,igp)) !in principle otw -> otw - ieta
1980 4735763519 : num = botsq(ig,igp) * rhotwgdp_igp
1981 4735763519 : den = omegame0i_io + otw
1982 4735763519 : den2 = den ** 2
1983 4828216932 : if (den2 > zcut2) then
1984 4732685542 : ket(ig,ispinor, iw) = ket(ig,ispinor,iw) + num/(den*otw) * theta_mu_minus_e0i
1985 : else
1986 : ket(ig,ispinor,iw) = ket(ig,ispinor,iw) + &
1987 3077977 : num * CMPLX(den,twofm1_zcut) / ((den2 + twofm1_zcut2) * otw) * theta_mu_minus_e0i
1988 : end if
1989 : end do ! ig
1990 : end do ! igp
1991 : end do ! iw
1992 : end if ! not totally empty
1993 :
1994 3114708 : if (.not. fully_occupied) then
1995 : ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(e_s-\mu) / (\omega-\omegat_{G1G2}-e_s+i\delta)
1996 1040775 : twofm1_zcut = -zcut
1997 1040775 : twofm1_zcut2 = twofm1_zcut**2
1998 : !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den, den2)
1999 18220966 : do iw=1,nomega
2000 17180191 : omegame0i_io = omegame0i(iw)
2001 : !if (iw > 1 .and. abs(omegame0i(iw) - omegame0i(iw-1)) < tol_omega) then
2002 : ! ket(:,:,iw) = ket(:,:,iw-1); cycle
2003 : !end if
2004 :
2005 464727215 : do igp=1,npwc
2006 446506249 : rhotwgdp_igp = rhotwgp(igp, ispinor)
2007 31044628495 : do ig=1,npwc
2008 30580942055 : otw = DBLE(otq(ig,igp)) !in principle otw -> otw + ieta
2009 30580942055 : num = botsq(ig,igp) * rhotwgdp_igp
2010 30580942055 : den = omegame0i_io - otw
2011 30580942055 : den2 = den ** 2
2012 31027448304 : if (den2 > zcut2) then
2013 30580025061 : ket(ig,ispinor,iw) = ket(ig,ispinor, iw) + num / (den*otw) * (one-theta_mu_minus_e0i)
2014 : else
2015 : ket(ig,ispinor, iw) = ket(ig,ispinor,iw) + &
2016 916994 : num * CMPLX(den,twofm1_zcut) / ((den2 + twofm1_zcut2) * otw) * (one-theta_mu_minus_e0i)
2017 : end if
2018 : end do ! ig
2019 : end do ! igp
2020 : end do ! iw
2021 : end if ! not fully occupied
2022 :
2023 : end do ! ispinor
2024 :
2025 582435912 : ket=ket*half
2026 :
2027 : case (PPM_LINDEN_HORSH, PPM_ENGEL_FARID)
2028 3840 : ABI_CHECK(nspinor == 1, "nspinor/=1 not allowed")
2029 :
2030 : ! rho-twiddle(G) is formed, introduce rhotwgdpcc, for speed reason
2031 11520 : ABI_MALLOC(rhotwgdpcc, (npwx))
2032 :
2033 3840 : ff = theta_mu_minus_e0i ! occupation number f (include poles if ...)
2034 3840 : twofm1 = two*ff-one ! 2f-1
2035 3840 : twofm1_zcut = twofm1*zcut
2036 107520 : rhotwgdpcc(:) = CONJG(rhotwgp(:, 1))
2037 :
2038 33280 : do iw=1,nomega
2039 29440 : omegame0i_io = omegame0i(iw)
2040 29440 : ct = czero_gw
2041 824320 : do ii=1,npwc ! Loop over the DM bands
2042 794880 : num = czero_gw
2043 :
2044 794880 : select case (ppm%model)
2045 : case (PPM_LINDEN_HORSH)
2046 : ! Calculate \beta (eq. 106 pag 47)
2047 11128320 : do ig=1,npwc
2048 11128320 : num = num + rhotwgdpcc(ig)*eig(ig,ii)
2049 : end do
2050 397440 : numf=num*CONJG(num) !MG this means that we cannot do SCGW
2051 397440 : numf=numf*botsq(ii,1)
2052 :
2053 : case (PPM_ENGEL_FARID)
2054 11128320 : do ig=1,npwc
2055 11128320 : num = num + rhotwgdpcc(ig)*botsq(ig,ii)
2056 : end do
2057 397440 : numf = num*CONJG(num) !MG this means that we cannot do SCGW
2058 :
2059 : case default
2060 794880 : ABI_ERROR("Wrong ppm%model")
2061 : end select
2062 :
2063 794880 : otw=DBLE(otq(ii,1)) ! in principle otw -> otw - ieta
2064 794880 : den=omegame0i_io+otw*twofm1
2065 :
2066 824320 : if (den**2 > zcut**2) then
2067 794880 : inv_den=one/den
2068 794880 : ct=ct+numf*inv_den
2069 : else
2070 0 : inv_den = one/((den**2+twofm1_zcut**2))
2071 0 : ct = ct + numf*CMPLX(den,twofm1_zcut)*inv_den
2072 : end if
2073 :
2074 : end do ! ii DM bands
2075 33280 : sigcme(iw) = ct*half
2076 :
2077 : !if (ppm%model == PPM_ENGEL_FARID) then
2078 : !ct = dot_product(ket(:, iw), ket(:, iw))
2079 : !if (abs(sigcme(iw) - ct) > tol12) then
2080 : ! ABI_ERROR("foo bar")
2081 : !end if
2082 : !end if
2083 : end do ! iw
2084 :
2085 3840 : ABI_FREE(rhotwgdpcc)
2086 :
2087 : case default
2088 1557834 : ABI_BUG(sjoin('Wrong ppm%model:',itoa(ppm%model)))
2089 : end select
2090 :
2091 1557834 : end subroutine ppm_calc_sigc
2092 : !!***
2093 :
2094 : !----------------------------------------------------------------------
2095 :
2096 : !!****f* m_ppmodel/ppm_rotate_iqbz
2097 : !! NAME
2098 : !! ppm_rotate_iqbz
2099 : !!
2100 : !! FUNCTION
2101 : !! Symmetrize the plasmonpole parameters in the full BZ.
2102 : !!
2103 : !! INPUTS
2104 : !! iq_bz=Index of the q-point in the BZ where the ppmodel parameters are wanted.
2105 : !! Gsph<gsphere_t>=data related to the G-sphere.
2106 : !! Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
2107 : !! Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
2108 : !! iq_ibz=Index of the q-point in the BZ.
2109 : !! npwe=number of G vectors for the correlation part
2110 : !! nomega=number of frequencies in $\epsilon^{-1}$
2111 : !! omega=frequencies in epsm1_ggw
2112 : !! epsm1_ggw(npwe,npwe,nomega)=the inverse dielctric matrix
2113 : !! ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
2114 : !! gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
2115 : !! nfftf=the number of points in the FFT mesh (for this processor)
2116 : !! rhor_tot(nfftf)=the total charge in real space
2117 : !!
2118 : !! SIDE EFFECTS
2119 : !! ppm<ppmodel_t>=data type containing information on the plasmonpole technique.
2120 : !! Internal tables are modified so that they (point|store) the plasmon-pole parameters
2121 : !! for the specified q-point in the BZ.
2122 : !!
2123 : !! SOURCE
2124 :
2125 0 : subroutine ppm_rotate_iqbz(ppm, iq_bz, Cryst, Qmesh, Gsph, npwe, nomega, omega, epsm1_ggw, &
2126 0 : nfftf, ngfftf, rhor_tot)
2127 :
2128 : !Arguments ------------------------------------
2129 : !scalars
2130 : class(ppmodel_t),target,intent(inout) :: ppm
2131 : integer,intent(in) :: nfftf,npwe,nomega,iq_bz
2132 : type(crystal_t),intent(in) :: Cryst
2133 : type(gsphere_t),intent(in) :: Gsph
2134 : type(kmesh_t),intent(in) :: Qmesh
2135 : !arrays
2136 : integer,intent(in) :: ngfftf(18)
2137 : real(dp),intent(in) :: rhor_tot(nfftf)
2138 : complex(dp),intent(in) :: omega(nomega)
2139 : complex(gwp),intent(in) :: epsm1_ggw(npwe,npwe,nomega)
2140 :
2141 : !Local variables-------------------------------
2142 : !scalars
2143 : integer :: iq_ibz,itim_q,isym_q,iq_curr
2144 : logical :: q_isirred
2145 : !character(len=500) :: msg
2146 : !arrays
2147 : real(dp) :: qbz(3)
2148 : ! *********************************************************************
2149 :
2150 : ! Save the index of the q-point in the BZ for checking purpose.
2151 0 : ppm%iq_bz = iq_bz
2152 :
2153 0 : call qmesh%get_bz_item(iq_bz, qbz, iq_ibz, isym_q, itim_q, isirred=q_isirred)
2154 0 : iq_curr = iq_ibz; if (ppm%mqmem == 0) iq_curr = 1
2155 :
2156 : ! =======================================================
2157 : ! ==== Branching for in-core or out-of-core solution ====
2158 : ! =======================================================
2159 :
2160 : ! Allocate the tables for this q_ibz
2161 : !print *, "ppm%has_qibz(iq_ibz)", ppm%has_qibz(iq_ibz), "q_isirred:", q_isirred
2162 0 : if (ppm%has_qibz(iq_ibz) == PPM_NOTAB) call ppm%malloc_iqibz(iq_ibz)
2163 :
2164 0 : if (ppm%has_qibz(iq_ibz) == PPM_TAB_ALLOCATED) then
2165 : ! Calculate the ppmodel tables for this q_ibz
2166 0 : call ppm%new_setup(iq_ibz, Cryst, Qmesh, npwe, nomega, omega, epsm1_ggw, nfftf, Gsph%gvec, ngfftf, rhor_tot)
2167 : end if
2168 :
2169 : ! Allocate memory if not done yet.
2170 : #ifdef FC_LLVM
2171 : !FIXME I don't understand why LLVM fails here...
2172 : !I put preproc so others know extra spaces are on purpose
2173 : ABI_REMALLOC(ppm%bigomegatwsq_qbz_vals, (ppm%npwc, ppm%dm2_botsq) )
2174 : ABI_REMALLOC(ppm%omegatw_qbz_vals, (ppm%npwc, ppm%dm2_otq) )
2175 : ABI_REMALLOC(ppm%eigpot_qbz_vals, (ppm%dm_eig, ppm%dm_eig) )
2176 : #else
2177 0 : ABI_REMALLOC(ppm%bigomegatwsq_qbz_vals, (ppm%npwc, ppm%dm2_botsq))
2178 0 : ABI_REMALLOC(ppm%omegatw_qbz_vals, (ppm%npwc, ppm%dm2_otq))
2179 0 : ABI_REMALLOC(ppm%eigpot_qbz_vals, (ppm%dm_eig, ppm%dm_eig))
2180 : #endif
2181 :
2182 0 : if (q_isirred) then
2183 : ! Symmetrization is not needed. Copy the data in memory and change the status.
2184 0 : ppm%bigomegatwsq_qbz_vals = ppm%bigomegatwsq(iq_ibz)%vals
2185 0 : ppm%omegatw_qbz_vals = ppm%omegatw(iq_ibz)%vals
2186 0 : ppm%eigpot_qbz_vals = ppm%eigpot(iq_ibz)%vals
2187 :
2188 : else
2189 : ! q-point in the BZ. Calculate new table for this q-point in the BZ. Beware: Dimensions should not change.
2190 0 : call ppm%get_qbz(Gsph, Qmesh, iq_bz, ppm%bigomegatwsq_qbz_vals, ppm%omegatw_qbz_vals, ppm%eigpot_qbz_vals)
2191 :
2192 : ! Release the table in the IBZ if required.
2193 0 : if (.not. ppm%keep_qibz(iq_ibz)) call ppm%table_free_iqibz(iq_ibz)
2194 : end if
2195 :
2196 0 : end subroutine ppm_rotate_iqbz
2197 : !!***
2198 :
2199 : !----------------------------------------------------------------------
2200 :
2201 : !!****f* m_ppmodel/ppm_new_setup
2202 : !! NAME
2203 : !! ppm_new_setup
2204 : !!
2205 : !! FUNCTION
2206 : !! Initialize some values of several arrays of the ppm datastructure
2207 : !! that are used in case of plasmonpole calculations
2208 : !! Just a wrapper around different plasmonpole routines.
2209 : !!
2210 : !! INPUTS
2211 : !! iq_ibz=Index of the q-point in the BZ.
2212 : !! Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
2213 : !! Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
2214 : !! npwe=number of G vectors for the correlation part
2215 : !! nomega=number of frequencies in $\epsilon^{-1}$
2216 : !! omega=frequencies in epsm1_ggw
2217 : !! epsm1_ggw(npwe,npwe,nomega)=the inverse dielctric matrix
2218 : !! nfftf=the number of points in the FFT mesh (for this processor)
2219 : !! ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
2220 : !! rhor(nfftf)=the total charge in real space.
2221 : !!
2222 : !! SIDE EFFECTS
2223 : !! == if ppmodel 1 or 2 ==
2224 : !! %omegatw and %bigomegatwsq
2225 : !! == if ppmodel 3 ==
2226 : !! %omegatw, %bigomegatwsq and %eigpot
2227 : !! == if ppmodel 4 ==
2228 : !! %omegatw and %bigomegatwsq
2229 : !!
2230 : !! NOTES
2231 : !! * FFT parallelism not implemented.
2232 : !! * TODO: rhor_tot should be replaced by rhog_tot to avoid nq_ibz FFTs.
2233 : !!
2234 : !! SOURCE
2235 :
2236 19 : subroutine ppm_new_setup(ppm, iq_ibz, Cryst, Qmesh, npwe, nomega, omega, epsm1_ggw, nfftf, gvec, ngfftf, rhor_tot)
2237 :
2238 : !Arguments ------------------------------------
2239 : !scalars
2240 : class(ppmodel_t),intent(inout) :: ppm
2241 : integer,intent(in) :: nfftf,npwe,nomega,iq_ibz
2242 : type(kmesh_t),intent(in) :: Qmesh
2243 : type(crystal_t),intent(in) :: Cryst
2244 : !arrays
2245 : integer,intent(in) :: gvec(3,npwe),ngfftf(18)
2246 : real(dp),intent(in) :: rhor_tot(nfftf)
2247 : complex(dp),intent(in) :: omega(nomega)
2248 : complex(gwp),intent(in) :: epsm1_ggw(npwe,npwe,nomega)
2249 :
2250 : !Local variables-------------------------------
2251 : !scalars
2252 : real(dp) :: n_at_G_zero
2253 : character(len=500) :: msg
2254 : !scalars
2255 : real(dp) :: qpt(3)
2256 : ! *************************************************************************
2257 :
2258 19 : if (ppm%has_qibz(iq_ibz) /= PPM_TAB_ALLOCATED) then
2259 0 : ABI_ERROR(sjoin("ppmodel tables for iq_ibz:", itoa(iq_ibz), "are not allocated! has_qibz=", itoa(ppm%has_qibz(iq_ibz))))
2260 : end if
2261 :
2262 76 : qpt = Qmesh%ibz(:,iq_ibz)
2263 19 : ppm%has_qibz(iq_ibz) = PPM_TAB_STORED
2264 :
2265 : ! Calculate plasmonpole parameters
2266 19 : select case (ppm%model)
2267 :
2268 : case (PPM_NONE)
2269 0 : ABI_COMMENT('Skipping plasmonpole model calculation')
2270 :
2271 : case (PPM_GODBY_NEEDS)
2272 : ! Note: the q-dependence enters only through epsilon^-1.
2273 19 : call cppm1par(npwe, nomega, omega, ppm%drude_plsmf, epsm1_ggw, ppm%omegatw(iq_ibz)%vals, ppm%bigomegatwsq(iq_ibz)%vals)
2274 :
2275 : case (PPM_HYBERTSEN_LOUIE)
2276 : call cppm2par(qpt, npwe, epsm1_ggw(:,:,1), ngfftf, gvec, Cryst%gprimd, rhor_tot, nfftf, Cryst%gmet, &
2277 0 : ppm%bigomegatwsq(iq_ibz)%vals, ppm%omegatw(iq_ibz)%vals, ppm%invalid_freq)
2278 :
2279 : ! Quick-and-dirty change of the plasmon frequency. Never executed in standard runs.
2280 0 : if (ppm%force_plsmf > tol6) then
2281 : ! Integrate the real-space density
2282 0 : n_at_G_zero = SUM(rhor_tot(:))/nfftf
2283 : ! Change the prefactor
2284 0 : write(msg,'(2(a,es16.8))') 'Forced ppmfreq: ',ppm%force_plsmf*Ha_eV,' nelect/ucvol: ',n_at_G_zero
2285 0 : ABI_WARNING(msg)
2286 :
2287 0 : ppm%force_plsmf = (ppm%force_plsmf**2)/(four_pi*n_at_G_zero)
2288 0 : ppm%bigomegatwsq(iq_ibz)%vals = ppm%force_plsmf * ppm%bigomegatwsq(iq_ibz)%vals
2289 0 : ppm%omegatw(iq_ibz)%vals = ppm%force_plsmf * ppm%omegatw(iq_ibz)%vals
2290 0 : write(msg,'(a,es16.8)') 'Plasma frequency forced in HL ppmodel, new prefactor is: ',ppm%force_plsmf
2291 0 : ABI_WARNING(msg)
2292 : end if
2293 :
2294 : case (PPM_LINDEN_HORSH)
2295 : call cppm3par(qpt, npwe,epsm1_ggw(:,:,1), ngfftf,gvec, Cryst%gprimd, rhor_tot, nfftf, &
2296 0 : ppm%bigomegatwsq(iq_ibz)%vals, ppm%omegatw(iq_ibz)%vals(:,1), ppm%eigpot(iq_ibz)%vals)
2297 :
2298 : case (PPM_ENGEL_FARID)
2299 0 : if ((ALL(ABS(qpt)<1.0e-3))) qpt = GW_Q0_DEFAULT ! FIXME
2300 :
2301 : call cppm4par(qpt, npwe,epsm1_ggw(:,:,1), ngfftf, gvec, Cryst%gprimd, rhor_tot, nfftf, &
2302 0 : ppm%bigomegatwsq(iq_ibz)%vals, ppm%omegatw(iq_ibz)%vals(:,1))
2303 :
2304 : case default
2305 19 : ABI_BUG(sjoin('Wrong ppm%model:', itoa(ppm%model)))
2306 : end select
2307 :
2308 19 : end subroutine ppm_new_setup
2309 : !!***
2310 :
2311 : !!****f* m_ppmodel/ppm_print
2312 : !! NAME
2313 : !! ppm_print
2314 : !!
2315 : !! FUNCTION
2316 : !! Print info on object
2317 : !!
2318 : !! SOURCE
2319 :
2320 6 : subroutine ppm_print(ppm, units, header)
2321 :
2322 : !Arguments ------------------------------------
2323 : class(ppmodel_t),intent(in) :: ppm
2324 : integer,intent(in) :: units(:)
2325 : character(len=*),optional,intent(in) :: header
2326 :
2327 : !Local variables-------------------------------
2328 : character(len=500) :: msg
2329 : type(yamldoc_t) :: ydoc
2330 : !*************************************************************************
2331 :
2332 0 : msg = ' ==== Info on the ppm_t object ==== '; if (present(header)) msg=' ==== '//trim(adjustl(header))//' ==== '
2333 3 : call wrtout(units, msg)
2334 :
2335 3 : ydoc = yamldoc_open('Plasmonpole_params') !, width=11, real_fmt='(3f8.3)')
2336 : !call ydoc%add_string("gwr_task", )
2337 3 : call ydoc%add_int("dm2_botsq", ppm%dm2_botsq)
2338 3 : call ydoc%add_int("dm_eig", ppm%dm_eig)
2339 3 : call ydoc%add_int("dm2_otq", ppm%dm2_otq)
2340 3 : call ydoc%add_int("invalid_freq", ppm%invalid_freq)
2341 3 : call ydoc%add_int("model", ppm%model)
2342 3 : call ydoc%add_int("mqmem", ppm%mqmem)
2343 3 : call ydoc%add_int("nqibz", ppm%nqibz)
2344 3 : call ydoc%add_int("npwc", ppm%npwc)
2345 3 : call ydoc%add_int("userho", ppm%userho)
2346 3 : call ydoc%add_int("iq_bz", ppm%iq_bz)
2347 3 : call ydoc%add_real("drude_plsmf", ppm%drude_plsmf)
2348 3 : call ydoc%add_real("force_plsmf", ppm%force_plsmf)
2349 : !call ydoc%add_int1d("keep_qibz", ppm%keep_qibz)
2350 : !call ydoc%add_int1d("has_qibz", ppm%has_qibz)
2351 :
2352 3 : call ydoc%write_units_and_free(units)
2353 :
2354 3 : end subroutine ppm_print
2355 : !!***
2356 :
2357 : !----------------------------------------------------------------------
2358 :
2359 399 : end module m_ppmodel
2360 : !!***
|