Branch data Line data Source code
1 : : !!****m* ABINIT/m_exc_diago
2 : : !! NAME
3 : : !! m_exc_diago
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 2009-2026 ABINIT and EXC groups (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! SOURCE
14 : :
15 : : #if defined HAVE_CONFIG_H
16 : : #include "config.h"
17 : : #endif
18 : :
19 : : #include "abi_common.h"
20 : :
21 : : MODULE m_exc_diago
22 : :
23 : : use defs_basis
24 : : use m_bs_defs
25 : : use m_abicore
26 : : use m_errors
27 : : USE_MPI
28 : : use m_xmpi
29 : : use m_hdr
30 : : use m_sort
31 : : use m_slk
32 : :
33 : : use defs_datatypes, only : pseudopotential_type
34 : : use m_io_tools, only : open_file
35 : : use m_fstrings, only : int2char4
36 : : use m_numeric_tools, only : print_arr, hermitianize
37 : : use m_crystal, only : crystal_t
38 : : use m_kpts, only : listkk
39 : : use m_bz_mesh, only : kmesh_t
40 : : use m_ebands, only : ebands_t
41 : : use m_eprenorms, only : eprenorms_t
42 : : use m_wfd, only : wfdgw_t
43 : : use m_paw_hr, only : pawhur_t
44 : : use m_pawtab, only : pawtab_type
45 : : use m_exc_itdiago, only : exc_iterative_diago
46 : : use m_hide_lapack, only : xheev, xheevx, xgeev, xhegvx, xginv, xhdp_invert, xhegv
47 : : use m_hide_blas, only : xdotc, xgemm
48 : : use m_bse_io, only : exc_fullh_from_blocks, offset_in_file, rrs_of_glob, ccs_of_glob, &
49 : : & exc_read_bshdr, exc_skip_bshdr_mpio, exc_read_rblock_fio
50 : : use m_exc_spectra, only : build_spectra
51 : :
52 : : implicit none
53 : :
54 : : private
55 : :
56 : : #if defined HAVE_MPI1
57 : : include 'mpif.h'
58 : : #endif
59 : :
60 : : !#define DEV_MG_DEBUG_THIS
61 : :
62 : : public :: exc_diago_driver ! Driver routine for the direct diagonalization of the BSE Hamiltonian (main entry point)
63 : : !!***
64 : :
65 : : contains
66 : :
67 : : !!****f* m_exc_diago/exc_diago_driver
68 : : !! NAME
69 : : !! exc_diago_driver
70 : : !!
71 : : !! FUNCTION
72 : : !! Driver routine for the direct diagonalization of the Hermitian excitonic Hamiltonian.
73 : : !!
74 : : !! INPUTS
75 : : !! neh=Rank of the resonant block of the Hamiltonian.
76 : : !! BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
77 : : !! %exh=Name of the file storing the excitonic resonant part.
78 : : !!
79 : : !! OUTPUT
80 : : !! Eigenvalues and eigenvectors are written on file.
81 : : !!
82 : : !! SOURCE
83 : :
84 : 6 : subroutine exc_diago_driver(Wfd,Bsp,BS_files,KS_BSt,QP_BSt,Cryst,Kmesh,Psps,&
85 : 6 : & Pawtab,Hur,Hdr_bse,drude_plsmf,Epren)
86 : :
87 : : !Arguments ------------------------------------
88 : : !scalars
89 : : real(dp),intent(in) :: drude_plsmf
90 : : type(excparam),intent(in) :: BSp
91 : : type(excfiles),intent(in) :: BS_files
92 : : type(Hdr_type),intent(in) :: Hdr_bse
93 : : type(crystal_t),intent(in) :: Cryst
94 : : type(pseudopotential_type),intent(in) :: Psps
95 : : type(kmesh_t),intent(in) :: Kmesh
96 : : type(ebands_t),intent(in) :: KS_BSt,QP_BSt
97 : : type(wfdgw_t),intent(inout) :: Wfd
98 : : type(eprenorms_t),intent(in) :: Epren
99 : : !arrays
100 : : type(pawtab_type),intent(in) :: Pawtab(Cryst%ntypat*Wfd%usepaw)
101 : : type(pawhur_t),intent(in) :: Hur(Cryst%natom*Wfd%usepaw)
102 : :
103 : : !Local variables ------------------------------
104 : : !scalars
105 : : integer :: my_rank,master,comm,prtvol
106 : : complex(dp) :: exc_gap,gw_gap
107 : : logical :: eval_eigenstates
108 : : character(len=500) :: msg
109 : : !arrays
110 : 12 : real(dp) :: gaps(3,QP_BSt%nsppol)
111 : : !************************************************************************
112 : :
113 : : DBG_ENTER("COLL")
114 : :
115 : 6 : comm = Wfd%comm
116 : 6 : my_rank = Wfd%my_rank
117 : 6 : master = Wfd%master
118 : 6 : prtvol = Wfd%prtvol
119 : :
120 [ - + ]: 6 : if (BSp%have_complex_ene) then
121 : 0 : ABI_ERROR("Complex energies are not supported yet")
122 : : end if
123 : : !
124 : : ! This trick is needed to restart a CG run, use DDIAGO to calculate the spectra reusing an old BSEIG file.
125 [ - + - - ]: 6 : eval_eigenstates = (BS_files%in_eig == BSE_NOFILE) .or. (Bsp%algorithm == BSE_ALGO_CG)
126 : :
127 : : if (eval_eigenstates) then
128 : : !
129 : 11 : select case (BSp%algorithm)
130 : : case (BSE_ALGO_DDIAGO)
131 [ + + ]: 5 : if (BSp%use_coupling==0) then
132 : 4 : call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm)
133 [ + + ]: 4 : if(Bsp%do_ep_renorm) then
134 : 1 : call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm,Epren=Epren,Kmesh=Kmesh,Cryst=Cryst,elph_lifetime=.TRUE.)
135 : : end if
136 : : else
137 [ - + ]: 1 : if (Bsp%have_complex_ene) then
138 : : ! Solve Hv = ev with generic complex matrix.
139 : 0 : call exc_diago_coupling(BSp,BS_files,Hdr_bse,prtvol,comm)
140 : : else
141 : : ! Solve generalized eigenvalue problem F Hbar with Hbar Hermitian definitive positive matrix.
142 : 1 : call exc_diago_coupling_hegv(BSp,BS_files,Hdr_bse,prtvol,comm)
143 : : end if
144 : : end if
145 : :
146 : : case (BSE_ALGO_CG)
147 [ + - ]: 1 : if (BSp%use_coupling==0) then
148 : 1 : call exc_iterative_diago(Bsp,BS_files,Hdr_bse,prtvol,comm)
149 : : else
150 : 0 : ABI_ERROR("CG + coupling not coded")
151 : : end if
152 : :
153 : : case default
154 : 0 : write(msg,'(a,i0)')" Wrong value for Bsp%algorithm: ",Bsp%algorithm
155 [ + + - ]: 6 : ABI_ERROR(msg)
156 : : end select
157 : : !
158 [ + - ]: 6 : if (my_rank==master) then
159 : 6 : call QP_BSt%report_gap(header="QP bands",unit=std_out,gaps=gaps)
160 [ + - - + : 19 : gw_gap = MINVAL(gaps(2,:))
- - + + ]
161 : 6 : call exc_print_eig(BSp,BS_files%out_eig,gw_gap,exc_gap)
162 : : end if
163 : 6 : call xmpi_barrier(comm)
164 : : !
165 : : end if
166 : :
167 : 6 : call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm)
168 : :
169 : : ! Electron-phonon renormalization !
170 [ + + + + : 6 : if (BSp%algorithm == BSE_ALGO_DDIAGO .and. BSp%use_coupling == 0 .and. BSp%do_ep_renorm) then
+ + ]
171 : 1 : call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm,Epren=Epren)
172 : : end if
173 : :
174 : : DBG_EXIT("COLL")
175 : :
176 : 6 : end subroutine exc_diago_driver
177 : : !!***
178 : :
179 : : !----------------------------------------------------------------------
180 : :
181 : : !!****f* m_exc_diago/exc_diago_resonant
182 : : !! NAME
183 : : !! exc_diago_resonant
184 : : !!
185 : : !! FUNCTION
186 : : !! Calculates eigenvalues and eigenvectors of the Hermitian excitonic Hamiltonian (coupling is neglected).
187 : : !!
188 : : !! INPUTS
189 : : !! Bsp
190 : : !! BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
191 : : !! comm=MPI communicator.
192 : : !! bseig_fname=The name of the output file
193 : : !! prtvol=Verbosity level.
194 : : !!
195 : : !! OUTPUT
196 : : !! Eigenvalues and eigenvectors are written on file bseig_fname
197 : : !!
198 : : !! SOURCE
199 : :
200 : 5 : subroutine exc_diago_resonant(Bsp,BS_files,Hdr_bse,prtvol,comm,Epren,Kmesh,Cryst,elph_lifetime)
201 : :
202 : : !Arguments ------------------------------------
203 : : !scalars
204 : : integer,intent(in) :: comm,prtvol
205 : : logical,optional,intent(in) :: elph_lifetime
206 : : type(excparam),intent(in) :: BSp
207 : : type(excfiles),intent(in) :: BS_files
208 : : type(Hdr_type),intent(in) :: Hdr_bse
209 : : type(eprenorms_t),optional,intent(in) :: Epren
210 : : type(kmesh_t),optional,intent(in) :: Kmesh
211 : : type(crystal_t),optional,intent(in) :: Cryst
212 : :
213 : : !Local variables ------------------------------
214 : : !scalars
215 : : integer,parameter :: master=0
216 : : integer :: ii,it,mi,hreso_unt,eig_unt,exc_size,neh1,neh2,j
217 : : integer :: nsppol,il,iu,mene_found,nstates
218 : : integer :: nprocs,my_rank,fform,nene_printed,ierr
219 : : real(dp) :: exc_gap,exc_maxene,abstol
220 : : real(dp) :: vl,vu
221 : : logical :: use_scalapack,do_full_diago,diagonal_is_real
222 : : character(len=500) :: msg
223 : : character(len=fnlen) :: hreso_fname,bseig_fname
224 : : !arrays
225 : 5 : real(dp),allocatable :: exc_ene(:)
226 : 5 : complex(dp),allocatable :: exc_mat(:,:),exc_vec(:,:)
227 : : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
228 : : integer :: amode,mpi_fh,istwf_k,tbloc
229 : : integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker
230 : : integer :: block_sizes(2,3),array_of_sizes(2),gsub(2,2)
231 : : logical,parameter :: is_fortran_file=.TRUE.
232 : : real(dp),external :: PDLAMCH
233 : : type(slkmat_dp_t) :: Slk_mat,Slk_vec
234 : : type(slk_processor_t) :: Slk_processor
235 : : #endif
236 : :
237 : : integer :: ik, ic, iv, isppol, ireh, ep_ik, itemp
238 : : complex(dp) :: en
239 : :
240 : : real(dp) :: dksqmax
241 : 5 : integer,allocatable :: bs2eph(:,:)
242 : : integer :: sppoldbl, timrev
243 : : logical :: do_ep_renorm, do_ep_lifetime
244 : : integer :: ntemp
245 : : character(len=4) :: ts
246 : 5 : complex(dp),allocatable :: exc_vl(:,:),exc_ene_c(:)
247 : : complex(dp) :: ctemp
248 : : !! complex(dp),allocatable :: ovlp(:,:)
249 : : !************************************************************************
250 : :
251 : : DBG_ENTER("PERS")
252 : :
253 : 5 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
254 : :
255 [ - + ]: 5 : if (BSp%have_complex_ene) then ! QP lifetimes are not included
256 : 0 : ABI_ERROR("complex energies not coded yet")
257 : : end if
258 : :
259 [ + + + - : 11 : if (ANY(Bsp%nreh/=Bsp%nreh(1))) then
- + ]
260 : 0 : write(std_out,*)" Bsp%nreh: ",Bsp%nreh
261 : 0 : write(msg,'(a)')" BSE code does not support different number of transitions for the two spin channels"
262 : 0 : ABI_WARNING(msg)
263 : : end if
264 : :
265 : 5 : nsppol = Hdr_bse%nsppol
266 [ + + ]: 11 : exc_size = SUM(BSp%nreh)
267 : 5 : nstates = BSp%nstates; do_full_diago=(Bsp%nstates==exc_size)
268 : :
269 : 5 : neh1 = Bsp%nreh(1); neh2 = neh1
270 : : if (Hdr_bse%nsppol==2) neh2 = Bsp%nreh(2)
271 : :
272 : : ! Scalapack is disabled due to portability issues in slk_read
273 : : ! This part should be rewritten with hdf5 + mpi-io
274 : :
275 : : use_scalapack = .FALSE.
276 : : !#if defined HAVE_LINALG_SCALAPACK
277 : : ! use_scalapack = (nprocs > 1)
278 : : !#endif
279 : : if (use_scalapack .and. nsppol == 2) then
280 : : use_scalapack = .False.
281 : : ABI_WARNING("Scalapack with nsppol==2 not yet available. Using sequential version")
282 : : end if
283 : :
284 [ - + ]: 5 : if (.not.use_scalapack .and. my_rank/=master) GOTO 10 ! Inversion is done by master only.
285 : :
286 [ - + ]: 5 : nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
287 : :
288 [ + + ]: 5 : if (BS_files%in_hreso /= BSE_NOFILE) then
289 : 1 : hreso_fname = BS_files%in_hreso
290 : : else
291 : 4 : hreso_fname = BS_files%out_hreso
292 : : end if
293 : :
294 : 5 : bseig_fname = BS_files%out_eig
295 [ - + ]: 5 : if (BS_files%in_eig /= BSE_NOFILE) then
296 : 0 : ABI_ERROR("BS_files%in_eig is defined!")
297 : : end if
298 : :
299 : 5 : write(msg,'(a,i0)')' Direct diagonalization of the resonant excitonic Hamiltonian, Matrix size= ',exc_size
300 [ + + ]: 15 : call wrtout([std_out, ab_out], msg)
301 : :
302 [ - + + - : 15 : ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
+ - + - +
- - + -
+ ]
303 [ - + + - : 15 : ABI_MALLOC_OR_DIE(exc_ene_c,(exc_size), ierr)
+ - + - +
- - + -
+ ]
304 : :
305 : 5 : do_ep_renorm = .FALSE.
306 : 5 : ntemp = 1
307 : 5 : do_ep_lifetime = .FALSE.
308 [ + + + + ]: 5 : if(BSp%do_ep_renorm .and. present(Epren)) then
309 : 1 : do_ep_renorm = .TRUE.
310 : 1 : ntemp = Epren%ntemp
311 [ + - ]: 1 : if(present(elph_lifetime)) then
312 : 1 : do_ep_lifetime = elph_lifetime
313 : : end if
314 : : end if
315 : :
316 : : if (do_ep_renorm) then
317 [ - + ]: 1 : ABI_CHECK(nsppol == 1, "Nsppol == 2 not supported with elphon renormalizations")
318 : : end if
319 : :
320 : : SELECT CASE (use_scalapack)
321 : : CASE (.FALSE.)
322 : :
323 : 5 : write(msg,'(a)')". Using LAPACK sequential version. "
324 [ + + ]: 15 : call wrtout([std_out, ab_out], msg)
325 : 5 : write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ', exc_size*dp*b2Mb,' Mb. '
326 : 5 : call wrtout(std_out, msg)
327 : :
328 : 5 : write(msg,'(a,f8.1,a)')' Allocating excitonic hamiltonian. Memory required: ',exc_size**2*dp*b2Mb,' Mb.'
329 : 5 : call wrtout(std_out, msg, do_flush=.True.)
330 : :
331 [ - + + - : 20 : ABI_MALLOC_OR_DIE(exc_mat,(exc_size,exc_size), ierr)
- + + - +
- + - + -
- + - + ]
332 : :
333 [ + + ]: 5 : if (do_ep_renorm) then
334 [ - + + - : 3 : ABI_MALLOC_OR_DIE(exc_vl,(exc_size,exc_size),ierr)
- + + - +
- - + -
+ ]
335 : : end if
336 : : !exc_mat = HUGE(zero)
337 : : !
338 : : ! Read data from file.
339 [ - + ]: 5 : if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
340 : 0 : ABI_ERROR(msg)
341 : : end if
342 : : !
343 : : ! Read the header and perform consistency checks.
344 : 5 : call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
345 [ - + ]: 5 : ABI_CHECK(ierr==0,"Fatal error, cannot continue")
346 : : !
347 : : ! Construct full resonant block using Hermiticity.
348 : 5 : diagonal_is_real = .not.Bsp%have_complex_ene
349 : 5 : call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
350 [ - + ]: 5 : ABI_CHECK(ierr==0,"Fatal error, cannot continue")
351 : :
352 : 5 : close(hreso_unt)
353 : :
354 [ + + ]: 5 : if (do_ep_renorm) then
355 : 1 : write(std_out,'(a)') "Mapping kpts from bse to eph"
356 : 1 : sppoldbl = 1 !; if (any(Cryst%symafm == -1) .and. Epren%nsppol == 1) nsppoldbl=2
357 [ - + + - : 3 : ABI_MALLOC(bs2eph, (Kmesh%nbz*sppoldbl, 6))
+ - + - -
+ - + ]
358 : 1 : timrev = 1
359 : : call listkk(dksqmax, Cryst%gmet, bs2eph, Epren%kpts, Kmesh%bz, Epren%nkpt, Kmesh%nbz, Cryst%nsym, &
360 [ + - ]: 1 : sppoldbl, Cryst%symafm, Cryst%symrel, timrev, xmpi_comm_self, use_symrec=.False.)
361 : : end if
362 : :
363 [ + + ]: 19 : do itemp = 1, ntemp
364 : :
365 : : !TODO should find a way not to read again and again !
366 : : ! but without storing it twice !!!
367 : : !exc_mat = HUGE(zero)
368 : : !
369 : : ! Read data from file.
370 [ - + ]: 14 : if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
371 : 0 : ABI_ERROR(msg)
372 : : end if
373 : : !
374 : : ! Read the header and perform consistency checks.
375 : 14 : call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
376 [ - + ]: 14 : ABI_CHECK(ierr==0,"Fatal error, cannot continue")
377 : : !
378 : : ! Construct full resonant block using Hermiticity.
379 : 14 : diagonal_is_real = .not.Bsp%have_complex_ene
380 : 14 : call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
381 [ - + ]: 14 : ABI_CHECK(ierr==0,"Fatal error, cannot continue")
382 : :
383 : 14 : close(hreso_unt)
384 : :
385 : 14 : bseig_fname = BS_files%out_eig
386 : :
387 [ + + ]: 14 : if (do_ep_renorm) then
388 : 10 : write(std_out,'(a,i4)') "Will perform elphon renormalization for itemp = ",itemp
389 : :
390 : 10 : call int2char4(itemp,ts)
391 : :
392 [ + - ]: 10 : bseig_fname = TRIM(BS_files%out_eig) // TRIM("_T") // ts
393 : :
394 : : ! Should patch the diagonal of exc_mat
395 : :
396 [ + + ]: 20 : do isppol = 1, BSp%nsppol
397 [ + + ]: 980 : do ireh = 1, BSp%nreh(isppol)
398 : 960 : ic = BSp%Trans(ireh,isppol)%c
399 : 960 : iv = BSp%Trans(ireh,isppol)%v
400 : 960 : ik = BSp%Trans(ireh,isppol)%k ! In the full bz
401 : 960 : en = BSp%Trans(ireh,isppol)%en
402 : :
403 : 960 : ep_ik = bs2eph(ik,1)
404 : :
405 : : !TODO support multiple spins !
406 [ - + ]: 960 : if(ABS(en - (Epren%eigens(ic,ep_ik,isppol)-Epren%eigens(iv,ep_ik,isppol)+BSp%mbpt_sciss)) > tol3) then
407 : 0 : ABI_ERROR("Eigen from the transition does not correspond to the EP file !")
408 : : end if
409 : 960 : exc_mat(ireh,ireh) = exc_mat(ireh,ireh) + (Epren%renorms(1,ic,ik,isppol,itemp) - Epren%renorms(1,iv,ik,isppol,itemp))
410 : :
411 : : ! Add lifetime
412 [ + - ]: 970 : if(do_ep_lifetime) then
413 : : exc_mat(ireh,ireh) = exc_mat(ireh,ireh) - j_dpc*(Epren%linewidth(1,ic,ik,isppol,itemp) &
414 : 960 : & + Epren%linewidth(1,iv,ik,isppol,itemp))
415 : : end if
416 : :
417 : : end do
418 : : end do
419 : :
420 : : end if
421 : :
422 [ + + ]: 14 : if (do_full_diago) then
423 [ + + ]: 13 : if(do_ep_renorm) then
424 : 10 : call wrtout(std_out," Full diagonalization with XGEEV... ")
425 [ - + + - : 30 : ABI_MALLOC(exc_vec,(exc_size,exc_size))
- + + - -
+ - + ]
426 : 10 : call xgeev('V','V',exc_size,exc_mat,exc_size,exc_ene_c,exc_vl,exc_size,exc_vec,exc_size)
427 [ + + + + ]: 93130 : exc_mat(:,1:nstates) = exc_vec
428 [ - + ]: 10 : ABI_FREE(exc_vec)
429 : : else
430 : 3 : call wrtout(std_out," Full diagonalization with XHEEV... ")
431 : 3 : call xheev("Vectors","Upper",exc_size,exc_mat,exc_ene)
432 [ + + ]: 1251 : exc_ene_c(:) = exc_ene(:)
433 : : end if
434 : : else
435 : 1 : call wrtout(std_out," Partial diagonalization with XHEEVX... ")
436 : 1 : abstol=zero; il=1; iu=nstates
437 [ - + + - : 4 : ABI_MALLOC_OR_DIE(exc_vec,(exc_size,nstates),ierr)
- + + - +
- + - + -
- + - + ]
438 : 1 : call xheevx("Vectors","Index","Upper",exc_size,exc_mat,vl,vu,il,iu,abstol,mene_found,exc_ene,exc_vec,exc_size)
439 [ + + + + ]: 3851 : exc_mat(:,1:nstates) = exc_vec
440 [ + + ]: 385 : exc_ene_c(:) = exc_ene(:)
441 [ - + ]: 1 : ABI_FREE(exc_vec)
442 : : end if
443 : : !
444 : : ! ==============================================
445 : : ! === Now exc_mat contains the eigenvectors ====
446 : : ! ==============================================
447 : :
448 : : ! * Write the final results.
449 [ + - ]: 14 : call wrtout(std_out,' Writing eigenvalues and eigenvectors to file: '//TRIM(bseig_fname))
450 : :
451 [ - + ]: 14 : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
452 : 0 : ABI_ERROR(msg)
453 : : end if
454 : :
455 : : !!! !DBYG
456 : : !!! !Compute overlap matrix
457 : : !!! ABI_MALLOC(ovlp,(exc_size,exc_size))
458 : : !!! do mi=1,nstates
459 : : !!! do ireh=1,nstates
460 : : !!! ovlp(mi,ireh) = xdotc(exc_size,exc_vl(:,mi),1,exc_mat(:,ireh),1)
461 : : !!! if(mi==ireh) then
462 : : !!! !if(ABS(ovlp(mi,ireh)) < 0.999) then
463 : : !!! ! write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
464 : : !!! !end if
465 : : !!! else
466 : : !!! if(ABS(ovlp(mi,ireh)) > 0.001) then
467 : : !!! write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
468 : : !!! end if
469 : : !!! end if
470 : : !!! end do
471 : : !!! end do
472 : : !!! !call xgemm("C","N",exc_size,nstates,nstates,cone,exc_vl,exc_size,exc_mat,exc_size,czero,ovlp,nstates)
473 : :
474 : : !!! write(777,*) ovlp
475 : : !!! ABI_FREE(ovlp)
476 : : !!! !ENDDBYG
477 : :
478 : : !% fform = 1002 ! FIXME
479 : : !% call hdr_io_int(fform,Hdr_bse,2,eig_unt)
480 : :
481 : 14 : write(eig_unt) do_ep_lifetime
482 : 14 : write(eig_unt) exc_size, nstates
483 : 14 : write(eig_unt) exc_ene_c(1:nstates)
484 [ + + ]: 2232 : do mi=1,nstates
485 : 2218 : write(eig_unt) exc_mat(1:exc_size,mi)
486 [ + + ]: 2232 : if(do_ep_lifetime) then
487 : 960 : write(eig_unt) exc_vl(1:exc_size,mi)
488 : : end if
489 : : end do
490 : :
491 : 47 : close(eig_unt)
492 : :
493 : : end do ! itemp
494 : :
495 [ - + ]: 5 : ABI_FREE(exc_mat)
496 [ + + ]: 15 : if (do_ep_renorm) then
497 [ - + ]: 1 : ABI_FREE(exc_vl)
498 [ - + ]: 1 : ABI_FREE(bs2eph)
499 : : end if
500 : :
501 : : CASE (.TRUE.)
502 : :
503 : : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
504 : : if (nsppol==2) then
505 : : ABI_WARNING("nsppol==2 + scalapack not coded yet")
506 : : end if
507 : :
508 : : istwf_k=1; tbloc=50
509 : : write(msg,'(2(a,i0))')". Using scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
510 : : call wrtout([std_out, ab_out], msg)
511 : :
512 : : write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ',exc_size*dp*b2Mb,' Mb. '
513 : : call wrtout(std_out, msg)
514 : : !
515 : : ! Init scaLAPACK environment.
516 : : call Slk_processor%init(comm)
517 : : !
518 : : ! Init scaLAPACK matrices
519 : : call Slk_mat%init(exc_size,exc_size,Slk_processor,istwf_k)
520 : : call Slk_vec%init(exc_size,exc_size,Slk_processor,istwf_k)
521 : : !
522 : : ! Open the file with MPI-IO and skip the record.
523 : : amode=MPI_MODE_RDONLY
524 : :
525 : : call MPI_FILE_OPEN(comm, hreso_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
526 : : ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
527 : :
528 : : ! Skip the header and find the offset for reading the matrix.
529 : : call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
530 : : !
531 : : ! Read scaLAPACK matrix from the file.
532 : : if (nsppol==1) then
533 : : call slk_read(Slk_mat,"Upper","Hermitian",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
534 : : else
535 : : array_of_sizes = (/exc_size,exc_size/)
536 : : block_sizes(:,1) = (/neh1,neh1/)
537 : : block_sizes(:,2) = (/neh2,neh2/)
538 : : block_sizes(:,3) = (/neh1,neh2/)
539 : : ABI_ERROR("Not tested")
540 : : !call slk_read_from_blocks(Slk_mat,array_of_sizes,block_sizes,is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
541 : : end if
542 : :
543 : : call MPI_FILE_CLOSE(mpi_fh, ierr)
544 : : ABI_CHECK_MPI(ierr,"FILE_CLOSE")
545 : :
546 : : if (do_full_diago) then
547 : : call wrtout(std_out," Performing full diagonalization with scaLAPACK...")
548 : : call slk_mat%heev("Vectors","Upper",Slk_vec,exc_ene)
549 : : else
550 : : call wrtout(std_out," Performing partial diagonalization with scaLAPACK...")
551 : : il=1; iu=nstates; abstol=zero !ABSTOL = PDLAMCH(comm,'U')
552 : : call slk_mat%pzheevx("Vectors","Index","Upper",vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
553 : : end if
554 : :
555 : : exc_ene_c(:) = exc_ene(:)
556 : :
557 : : call Slk_mat%free()
558 : :
559 : : call wrtout(std_out,' Writing eigenvalues/vectors to file: '//TRIM(bseig_fname), do_flush=.True.)
560 : :
561 : : ! Write distributed matrix on file bseig_fname with Fortran records.
562 : : if (my_rank==master) then ! Write exc eigenvalues. Vectors will be appended in slk_write.
563 : : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
564 : : ABI_ERROR(msg)
565 : : end if
566 : : write(eig_unt) exc_size, nstates
567 : : write(eig_unt) exc_ene_c(1:nstates)
568 : : close(eig_unt)
569 : : end if
570 : :
571 : : call xmpi_barrier(comm)
572 : : !
573 : : ! Open the file with MPI-IO and skip the record.
574 : : amode=MPI_MODE_RDWR
575 : :
576 : : call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
577 : : ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
578 : :
579 : : !call MPI_FILE_SYNC(mpi_fh,ierr)
580 : :
581 : : ehdr_offset = 0
582 : : call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
583 : : call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
584 : :
585 : : write(std_out,*)"Writing nstates ",nstates
586 : : gsub(:,1) = (/1,1/)
587 : : gsub(:,2) = (/exc_size,nstates/)
588 : : call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
589 : :
590 : : call MPI_FILE_CLOSE(mpi_fh, ierr)
591 : : ABI_CHECK_MPI(ierr,"FILE_CLOSE")
592 : :
593 : : call Slk_vec%free()
594 : : call Slk_processor%free()
595 : : call xmpi_barrier(comm)
596 : : #else
597 : : ABI_BUG("You should not be here!")
598 : : #endif
599 : :
600 : : END SELECT
601 : :
602 : : ! Order the eigenvalues
603 [ + + ]: 1354 : do ii=nstates,2,-1
604 [ + + ]: 378583 : do j=1,ii-1
605 [ + + ]: 378578 : if (DBLE(exc_ene_c(j)) > DBLE(exc_ene_c(j+1))) then
606 : 3583 : ctemp = exc_ene_c(j)
607 : 3583 : exc_ene_c(j) = exc_ene_c(j+1)
608 : 3583 : exc_ene_c(j+1) = ctemp
609 : : end if
610 : : end do
611 : : end do
612 : :
613 : :
614 : 5 : write(msg,'(a,i4)')' Excitonic eigenvalues in eV up to n= ',nene_printed
615 [ + + ]: 15 : call wrtout([std_out, ab_out], msg)
616 : :
617 [ + + ]: 27 : do it=0,(nene_printed-1)/8
618 [ + - + + ]: 192 : write(msg,'(8f10.5)') ( DBLE(exc_ene_c(ii))*Ha_eV, ii=1+it*8,MIN(it*8+8,nene_printed) )
619 [ + + ]: 71 : call wrtout([std_out, ab_out], msg)
620 : : end do
621 : :
622 [ + - - + : 1364 : exc_gap = MINVAL(DBLE(exc_ene_c(1:nstates)))
- - + + ]
623 [ + - - + : 1364 : exc_maxene = MAXVAL(DBLE(exc_ene_c(1:nstates)))
- - + + ]
624 : :
625 : 5 : write(msg,'(a,2(a,f7.2,2a),a)')ch10,&
626 : 5 : " First excitonic eigenvalue= ",exc_gap*Ha_eV, " [eV]",ch10,&
627 : 10 : " Last excitonic eigenvalue= ",exc_maxene*Ha_eV," [eV]",ch10,ch10
628 [ + + ]: 15 : call wrtout([std_out, ab_out], msg, do_flush=.True.)
629 : :
630 [ - + ]: 5 : ABI_FREE(exc_ene_c)
631 [ - + ]: 5 : ABI_FREE(exc_ene)
632 : :
633 : 5 : 10 call xmpi_barrier(comm)
634 : :
635 : : DBG_EXIT("PERS")
636 : :
637 [ - + - + ]: 5 : end subroutine exc_diago_resonant
638 : : !!***
639 : :
640 : : !----------------------------------------------------------------------
641 : :
642 : : !!****f* m_exc_diago/exc_print_eig
643 : : !! NAME
644 : : !! exc_print_eig
645 : : !!
646 : : !! FUNCTION
647 : : !! Print excitonic eigenvalues on std_out and ab_out.
648 : : !!
649 : : !! INPUTS
650 : : !! gw_gap=GW direct gap.
651 : : !! bseig_fname=The name of file containing eigenvalues and eigenvectors
652 : : !!
653 : : !! OUTPUT
654 : : !! exc_gap=Excitonic direct gap.
655 : : !! Additional info on the Excitonic spectrum are reported on standard output.
656 : : !!
657 : : !! SOURCE
658 : :
659 : 6 : subroutine exc_print_eig(BSp,bseig_fname,gw_gap,exc_gap)
660 : :
661 : : !Arguments ------------------------------------
662 : : !scalars
663 : : complex(dp),intent(in) :: gw_gap
664 : : complex(dp),intent(out) :: exc_gap
665 : : character(len=*),intent(in) :: bseig_fname
666 : : type(excparam),intent(in) :: BSp
667 : :
668 : : !Local variables ------------------------------
669 : : !scalars
670 : : integer :: nstates_read,ii,j,k,eig_unt,ieig,hsize_exp, hsize_read !,nstates
671 : : complex(dp) :: bind_energy,ctemp
672 : : character(len=500) :: msg
673 : : !type(Hdr_type) :: tmp_Hdr
674 : : !arrays
675 : 6 : integer,allocatable :: iperm(:)
676 : 6 : real(dp),allocatable :: exc_rene(:)
677 : 6 : complex(dp),allocatable :: exc_cene(:)
678 : : !************************************************************************
679 : :
680 : 6 : exc_gap = czero
681 : :
682 [ - + ]: 6 : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then
683 : 0 : ABI_ERROR(msg)
684 : : end if
685 : :
686 : 6 : read(eig_unt) ! do_ep_lifetime
687 : 6 : read(eig_unt) hsize_read, nstates_read
688 : :
689 [ + + + + ]: 12 : if (BSp%use_coupling==0) hsize_exp = SUM(Bsp%nreh)
690 [ + + + + ]: 7 : if (BSp%use_coupling>0) hsize_exp = 2*SUM(Bsp%nreh)
691 : :
692 [ - + ]: 6 : if (hsize_exp /= hsize_read) then
693 : 0 : write(msg,'(2(a,i0))')" Wrong dimension: read: ",hsize_read," expected= ",hsize_exp
694 : 0 : ABI_ERROR(msg)
695 : : end if
696 : :
697 [ - + + - : 18 : ABI_MALLOC(exc_cene,(nstates_read))
+ - + - -
+ - + ]
698 : 6 : read(eig_unt) exc_cene(:)
699 : :
700 [ - + + - : 18 : ABI_MALLOC(exc_rene,(nstates_read))
+ - + - -
+ - + ]
701 [ + - - + : 2048 : exc_rene = DBLE(exc_cene)
- - + + ]
702 : :
703 [ - + + - : 18 : ABI_MALLOC(iperm,(nstates_read))
+ - + - -
+ - + ]
704 [ + - + + : 6126 : iperm = (/(ii, ii=1,nstates_read)/)
+ - + + +
- - + - -
+ + ]
705 : :
706 : 6 : call sort_dp(nstates_read,exc_rene,iperm,tol6)
707 : :
708 [ - + ]: 6 : ABI_FREE(exc_rene)
709 [ - + ]: 6 : ABI_FREE(iperm)
710 : :
711 : : ! put in ascending order
712 [ + + ]: 2036 : do ii=nstates_read,2,-1
713 [ + + ]: 669278 : do j=1,ii-1
714 [ + - ]: 669272 : if (DBLE(exc_cene(j)) > DBLE(exc_cene(j+1))) then
715 : 0 : ctemp = exc_cene(j)
716 : 0 : exc_cene(j) = exc_cene(j+1)
717 : 0 : exc_cene(j+1) = ctemp
718 : : end if
719 : : end do
720 : : end do
721 : :
722 : 6 : exc_gap = DCMPLX(ABS(DBLE(exc_cene(1))),AIMAG(exc_cene(1)))
723 : :
724 [ + + ]: 2042 : do ii=1,nstates_read
725 [ + + ]: 2042 : if (ABS(DBLE(exc_cene(ii))) < DBLE(exc_gap)) then
726 : 383 : exc_gap = DCMPLX(ABS(DBLE(exc_cene(ii))),AIMAG(exc_cene(ii)))
727 : : end if
728 : : end do
729 : :
730 : 6 : bind_energy = gw_gap - exc_gap
731 : :
732 : : write(msg,"(3(a,2f6.2,2a))")&
733 : 6 : " GW direct gap ",gw_gap*Ha_eV, " [eV] ",ch10,&
734 : 6 : " EXC direct gap ",exc_gap*Ha_eV, " [eV] ",ch10,&
735 : 12 : " EXC binding energy ",bind_energy*Ha_eV," [eV] ",ch10
736 [ + + ]: 18 : call wrtout([std_out, ab_out], msg)
737 : :
738 : 6 : msg=' Excitonic eigenvalues up to the GW energy gap [eV]'
739 [ + + ]: 18 : call wrtout([std_out, ab_out], msg)
740 : :
741 [ - + ]: 390 : do ii=1,nstates_read
742 [ + + ]: 390 : if (DBLE(exc_cene(ii)) > zero) EXIT
743 : : end do
744 : :
745 [ + + ]: 96 : do j=ii,nstates_read
746 [ + + ]: 96 : if (DBLE(exc_cene(j)) > DBLE(gw_gap)) EXIT
747 : : end do
748 : 6 : j=j-1
749 : :
750 [ + + ]: 96 : do ieig=ii,j
751 : 90 : write(msg,'(i3,a,2f6.2,a)')ieig," (",exc_cene(ieig)*Ha_eV,")"
752 [ + + ]: 276 : call wrtout([std_out, ab_out], msg)
753 : : end do
754 : :
755 : 6 : ii=ii-1
756 [ + + ]: 22 : do j=ii,1,-1
757 [ + + ]: 22 : if (ABS(DBLE(exc_cene(j))) > DBLE(gw_gap)) EXIT
758 : : end do
759 : 6 : j=j+1
760 : :
761 : : ! This coding is not portable, write to ab_out has been disabled.
762 [ + + ]: 6 : if (ii>0) then
763 [ + + ]: 17 : do k=ii,j,-1
764 : 16 : write(msg,'(i3,a,2f6.2,a)')k," (",exc_cene(k)*Ha_eV,")"
765 : 17 : call wrtout(std_out, msg)
766 : : end do
767 : : end if
768 : :
769 : 6 : ABI_FREE(exc_cene)
770 : :
771 : 6 : close(eig_unt)
772 : :
773 : 6 : end subroutine exc_print_eig
774 : : !!***
775 : :
776 : : !----------------------------------------------------------------------
777 : :
778 : : !!****f* m_exc_diago/exc_diago_coupling
779 : : !! NAME
780 : : !! exc_diago_coupling
781 : : !!
782 : : !! FUNCTION
783 : : !! Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
784 : : !! of the non Hermitian excitonic Hamiltoninan (resonant + coupling).
785 : : !!
786 : : !! INPUTS
787 : : !! bseig_fname=The name of the output file.
788 : : !! Bsp
789 : : !! neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
790 : : !! comm=MPI communicator.
791 : : !! BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
792 : : !!
793 : : !! OUTPUT
794 : : !! Excitonic eigenvectors and eigenvalues are written on file BS_files%out_eig.
795 : : !!
796 : : !! SOURCE
797 : :
798 : 0 : subroutine exc_diago_coupling(Bsp,BS_files,Hdr_bse,prtvol,comm)
799 : :
800 : : !Arguments ------------------------------------
801 : : !scalars
802 : : integer,intent(in) :: comm,prtvol
803 : : type(excfiles),intent(in) :: BS_files
804 : : type(excparam),intent(in) :: BSp
805 : : type(Hdr_type),intent(in) :: Hdr_bse
806 : :
807 : : !Local variables ------------------------------
808 : : !scalars
809 : : integer,parameter :: master=0,ldvl=1
810 : : integer(i8b) :: bsize_ham
811 : : integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt,nsppol,nstates
812 : : integer :: bsz,block,bs1,bs2,jj, fform,row_sign, mi,it,nprocs,my_rank !itp
813 : : integer :: nene_printed,ierr
814 : : real(dp) :: exc_gap,exc_maxene,temp
815 : : logical :: diago_is_real,do_full_diago, do_ep_lifetime
816 : : character(len=500) :: msg
817 : : character(len=fnlen) :: hreso_fname,hcoup_fname,bseig_fname
818 : : !arrays
819 : 0 : complex(dp),allocatable :: exc_ham(:,:),exc_rvect(:,:),exc_ene(:),ovlp(:,:), cbuff(:,:)
820 : : complex(dp) :: vl_dpc(ldvl,1)
821 : : !************************************************************************
822 : :
823 : 0 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
824 : :
825 : 0 : nsppol = Hdr_bse%nsppol
826 [ # # ]: 0 : if (nsppol==2) then
827 : 0 : ABI_WARNING("nsppol==2 with coupling is still under development")
828 : : end if
829 : :
830 [ # # ]: 0 : if (nprocs > 1) then
831 : 0 : ABI_WARNING("Scalapack does not provide ZGEEV, diagonalization is done in sequential!")
832 : : end if
833 : :
834 [ # # ]: 0 : exc_size = 2*SUM(BSp%nreh)
835 : 0 : nstates = BSp%nstates
836 : 0 : do_full_diago = (exc_size==nstates)
837 [ # # ]: 0 : ABI_CHECK(do_full_diago,"Partial diago not coded yet")
838 : :
839 : 0 : bseig_fname = BS_files%out_eig
840 [ # # ]: 0 : if (BS_files%in_eig /= BSE_NOFILE) then
841 : 0 : ABI_ERROR("BS_files%in_eig is defined!")
842 : : end if
843 : : !
844 : : ! Only master performs the diagonalization since ScaLAPACK does not provide the parallel version of ZGEEV.
845 [ # # ]: 0 : if (my_rank/=master) GOTO 10
846 : :
847 : 0 : write(msg,'(a,i0)')' Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
848 [ # # ]: 0 : call wrtout([std_out, ab_out], msg)
849 : :
850 : 0 : bsize_ham = 2*dp*exc_size**2
851 : 0 : write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',bsize_ham*b2Gb,' Gb. '
852 : 0 : call wrtout(std_out, msg)
853 : :
854 [ # # # # : 0 : ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
# # # # #
# # # # #
# # # # ]
855 : :
856 : : write(msg,'(3a,f8.1,3a,f8.1,a)')&
857 : 0 : ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
858 : 0 : ' Memory-space requested: ',2*dp*exc_size*b2Gb,' Gb. ',ch10,&
859 : 0 : ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
860 : 0 : call wrtout(std_out, msg)
861 : :
862 [ # # # # : 0 : ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
# # # # #
# # # #
# ]
863 : :
864 [ # # ]: 0 : if (BS_files%in_hreso /= BSE_NOFILE) then
865 : 0 : hreso_fname = BS_files%in_hreso
866 : : else
867 : 0 : hreso_fname = BS_files%out_hreso
868 : : end if
869 : :
870 [ # # ]: 0 : call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(hreso_fname))
871 : :
872 [ # # ]: 0 : if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
873 : 0 : ABI_ERROR(msg)
874 : : end if
875 : : !
876 : : ! Read the header and perform consistency checks.
877 : 0 : call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
878 [ # # ]: 0 : ABI_CHECK(ierr==0,"Wrong header")
879 : : !
880 : : ! Construct resonant and anti-resonant part of the excitonic Hamiltonian using Hermiticity. File is always in double precision.
881 : : ! Fill exc_ham with ( R 0 )
882 : : ! ( 0 -R*)
883 : : !BEGINDEBUG
884 [ # # # # ]: 0 : exc_ham = HUGE(one)
885 : : !ENDDEBUG
886 : :
887 : 0 : row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene)
888 : 0 : call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
889 : 0 : close(hreso_unt)
890 : :
891 [ # # ]: 0 : if (BS_files%in_hcoup /= BSE_NOFILE) then
892 : 0 : hcoup_fname = BS_files%in_hcoup
893 : : else
894 : 0 : hcoup_fname = BS_files%out_hcoup
895 : : end if
896 : :
897 [ # # ]: 0 : call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(hcoup_fname))
898 [ # # ]: 0 : if (open_file(hcoup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
899 : 0 : ABI_ERROR(msg)
900 : : end if
901 : : !
902 : : ! Read the header and perform consistency checks.
903 : 0 : call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
904 [ # # ]: 0 : ABI_CHECK(ierr==0,"Wrong header")
905 : : !
906 : : ! Fill exc_ham with ( 0 C) to have ( R C )
907 : : ! (-C* 0) (-C* -R*)
908 : 0 : row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here
909 : 0 : call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
910 : :
911 : : !BEGINDEBUG
912 [ # # # # : 0 : if (ANY(exc_ham==HUGE(one))) then
# # # # ]
913 [ # # # # : 0 : write(msg,'(a,2(1x,i0))')"There is a bug in exc_fullh_from_blocks",COUNT(exc_ham==HUGE(one)),exc_size**2
# # ]
914 : 0 : ABI_WARNING(msg)
915 : 0 : bsz = Bsp%nreh(1)
916 [ # # # # : 0 : ABI_MALLOC(cbuff,(bsz,bsz))
# # # # #
# # # # #
# # ]
917 : 0 : block=0
918 [ # # ]: 0 : do jj=1,2*nsppol
919 [ # # ]: 0 : do ii=1,2*nsppol
920 : 0 : block=block+1
921 : 0 : bs1 = (ii-1)*bsz+1
922 : 0 : bs2 = (jj-1)*bsz+1
923 [ # # # # : 0 : cbuff = exc_ham(bs1:bs1+bsz-1,bs2:bs2+bsz-1)
# # # # #
# # # ]
924 [ # # # # : 0 : if (ANY(cbuff==HUGE(one))) then
# # # # ]
925 [ # # # # : 0 : write(std_out,*)" for block ",ii,jj," found ",COUNT(cbuff==HUGE(one))," wrong entries"
# # ]
926 : : end if
927 : : end do
928 : : end do
929 : :
930 [ # # ]: 0 : ABI_FREE(cbuff)
931 : 0 : ABI_ERROR("Cannot continue")
932 : : end if
933 : : !ENDDEBUG
934 : :
935 : 0 : close(hcoup_unt)
936 : : !
937 : : ! ======================================================
938 : : ! ==== Calculate right eigenvectors and eigenvalues ====
939 : : ! ======================================================
940 [ # # # # : 0 : ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,exc_size), ierr)
# # # # #
# # # #
# ]
941 : :
942 [ # # ]: 0 : if (do_full_diago) then
943 : 0 : call wrtout(std_out,"Complete direct diagonalization with xgeev...")
944 : 0 : call xgeev("No_left_eigen","Vectors",exc_size,exc_ham,exc_size,exc_ene,vl_dpc,ldvl,exc_rvect,exc_size)
945 : : else
946 : 0 : ABI_ERROR("Not implemented error")
947 : : end if
948 : :
949 [ # # ]: 0 : ABI_FREE(exc_ham)
950 : :
951 [ # # # # : 0 : exc_gap = MINVAL(ABS(DBLE (exc_ene(1:nstates))))
# # # # ]
952 [ # # # # : 0 : exc_maxene = MAXVAL(ABS(DBLE (exc_ene(1:nstates))))
# # # # ]
953 [ # # # # : 0 : temp = MAXVAL(ABS(AIMAG(exc_ene(1:nstates))))
# # # # ]
954 : :
955 : : write(msg,'(2(a,f7.2,2a),a,es9.2,2a)')&
956 : 0 : " First excitonic eigenvalue: ",exc_gap*Ha_eV, " [eV].",ch10,&
957 : 0 : " Last excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10,&
958 : 0 : " Largest imaginary part: ",temp*Ha_eV, " [eV] ",ch10
959 [ # # ]: 0 : call wrtout([std_out, ab_out], msg)
960 : :
961 [ # # ]: 0 : nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
962 : :
963 : : ! This is not portable as the the eigenvalues calculated by ZGEEV are not sorted.
964 : : ! Even two subsequent calculations with the same input on the same machine
965 : : ! might produce different orderings. Might sort the eigenvalues though, just for printing.
966 : :
967 : 0 : write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
968 : 0 : call wrtout(std_out,msg)
969 : :
970 [ # # ]: 0 : do it=0,(nene_printed-1)/4
971 [ # # # # ]: 0 : write(msg,'(8f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
972 : 0 : call wrtout(std_out,msg)
973 : : end do
974 : :
975 [ # # ]: 0 : call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file "//TRIM(bseig_fname))
976 : :
977 [ # # ]: 0 : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
978 : 0 : ABI_ERROR(msg)
979 : : end if
980 : :
981 : : !YG : new version with lifetime
982 : 0 : do_ep_lifetime = .FALSE.
983 : 0 : write(eig_unt) do_ep_lifetime
984 : :
985 : 0 : write(eig_unt)exc_size,nstates
986 [ # # ]: 0 : write(eig_unt)CMPLX(exc_ene(1:nstates),kind=dp)
987 [ # # ]: 0 : do mi=1,nstates
988 : 0 : write(eig_unt) exc_rvect(:,mi)
989 : : end do
990 : :
991 [ # # ]: 0 : ABI_FREE(exc_ene)
992 : :
993 [ # # # # : 0 : ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
# # # # #
# # # # #
# # # # ]
994 : :
995 : 0 : call wrtout(std_out,' Calculating overlap matrix... ')
996 : :
997 : : !do itp=1,nstates
998 : : ! do it=1,nstates
999 : : ! ovlp(it,itp) = xdotc(exc_size,exc_rvect(:,it),1,exc_rvect(:,itp),1)
1000 : : ! end do
1001 : : !end do
1002 : 0 : call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
1003 [ # # ]: 0 : ABI_FREE(exc_rvect)
1004 : :
1005 : 0 : call wrtout(std_out," Inverting overlap matrix... ")
1006 : :
1007 : : ! Version for generic complex matrix.
1008 : : !call xginv(ovlp,exc_size)
1009 : :
1010 : : ! The overlap is Hermitian definite positive.
1011 : 0 : call xhdp_invert("Upper",ovlp,nstates)
1012 : 0 : call hermitianize(ovlp,"Upper")
1013 : :
1014 [ # # ]: 0 : call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
1015 : :
1016 [ # # ]: 0 : do it=1,nstates
1017 [ # # ]: 0 : write(eig_unt) CMPLX(ovlp(:,it),kind=dp)
1018 : : end do
1019 : :
1020 [ # # ]: 0 : ABI_FREE(ovlp)
1021 : :
1022 : 0 : close(eig_unt)
1023 : :
1024 : 0 : 10 call xmpi_barrier(comm)
1025 : :
1026 [ # # ]: 0 : end subroutine exc_diago_coupling
1027 : : !!***
1028 : :
1029 : : !----------------------------------------------------------------------
1030 : :
1031 : : !!****f* m_exc_diago/exc_diago_coupling_hegv
1032 : : !! NAME
1033 : : !! exc_diago_coupling_hegv
1034 : : !!
1035 : : !! FUNCTION
1036 : : !! Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
1037 : : !! of the non Hermitian excitonic Hamiltonian (resonant + coupling).
1038 : : !!
1039 : : !! INPUTS
1040 : : !! bseig_fname=The name of the output file.
1041 : : !! Bsp
1042 : : !! neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
1043 : : !! comm=MPI communicator.
1044 : : !! BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
1045 : : !!
1046 : : !! OUTPUT
1047 : : !! Excitonic eigenvectors and eigenvalues are written to file BS_files%out_eig.
1048 : : !!
1049 : : !! SOURCE
1050 : :
1051 : 1 : subroutine exc_diago_coupling_hegv(Bsp,BS_files,Hdr_bse,prtvol,comm)
1052 : :
1053 : : !Arguments ------------------------------------
1054 : : !scalars
1055 : : integer,intent(in) :: comm,prtvol
1056 : : type(excparam),intent(in) :: BSp
1057 : : type(excfiles),intent(in) :: BS_files
1058 : : type(Hdr_type),intent(in) :: Hdr_bse
1059 : :
1060 : : !Local variables ------------------------------
1061 : : !scalars
1062 : : integer,parameter :: master=0
1063 : : integer(i8b) :: bsize_ham
1064 : : integer :: itype,il,iu,spin,row1,row2,pad_r1,pad_r2,neh1,neh2
1065 : : integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt
1066 : : integer :: fform,neig_found,nstates, mi,it,nprocs,my_rank
1067 : : integer :: nene_printed,nsppol,row_sign,ierr
1068 : : real(dp) :: exc_gap,exc_maxene,abstol,vl,vu
1069 : : character(len=500) :: msg
1070 : : character(len=fnlen) :: reso_fname,coup_fname,bseig_fname
1071 : : logical :: use_scalapack,do_full_diago,diago_is_real, do_ep_lifetime
1072 : : !arrays
1073 : 1 : real(dp),allocatable :: exc_ene(:) !,test_ene(:)
1074 : 1 : complex(dp),allocatable :: exc_ham(:,:),exc_rvect(:,:),fmat(:,:),ovlp(:,:)
1075 : : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
1076 : : integer,parameter :: istwfk1=1
1077 : : integer :: amode,mpi_fh,tbloc,mene_found,mpi_err,my_nel,nsblocks
1078 : : integer :: iloc,jloc,iglob,jglob,etype,slk_mask_type,offset_err,el,rrs_kind,ccs_kind
1079 : : !integer :: max_r,max_c
1080 : : integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker,my_offset
1081 : : integer :: gsub(2,2)
1082 : : logical,parameter :: is_fortran_file=.TRUE.
1083 : : complex(dp) :: ctmp
1084 : : integer,allocatable :: sub_block(:,:,:)
1085 : : integer,pointer :: myel2loc(:,:)
1086 : : complex(dp),allocatable :: tmp_cbuffer(:)
1087 : : character(50) :: uplo
1088 : : real(dp),external :: PDLAMCH
1089 : : type(slkmat_dp_t) :: Slk_F,Slk_Hbar,Slk_vec,Slk_ovlp !,Slk_tmp
1090 : : type(slk_processor_t) :: Slk_processor
1091 : : #endif
1092 : : !************************************************************************
1093 : :
1094 : 1 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
1095 : :
1096 : 1 : nsppol = Hdr_bse%nsppol
1097 [ - + ]: 1 : if (nsppol==2) then
1098 : 0 : ABI_WARNING("nsppol==2 is still under development!")
1099 : : end if
1100 : :
1101 : 1 : neh1 = BSp%nreh(1); neh2=neh1
1102 : : if (nsppol==2) neh2 = BSp%nreh(2)
1103 : :
1104 [ + + ]: 2 : exc_size = 2*SUM(Bsp%nreh)
1105 : 1 : nstates = Bsp%nstates
1106 : 1 : do_full_diago=(nstates==exc_size)
1107 : :
1108 : 1 : write(msg,'(a,i0)')'. Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
1109 [ + + ]: 3 : call wrtout([std_out, ab_out], msg)
1110 : :
1111 : 1 : bseig_fname = BS_files%out_eig
1112 [ - + ]: 1 : if (BS_files%in_eig /= BSE_NOFILE) then
1113 : 0 : ABI_ERROR("BS_files%in_eig is defined!")
1114 : : end if
1115 : :
1116 [ + - ]: 1 : if (BS_files%in_hreso /= BSE_NOFILE) then
1117 : 1 : reso_fname = BS_files%in_hreso
1118 : : else
1119 : 0 : reso_fname = BS_files%out_hreso
1120 : : end if
1121 [ + - ]: 1 : call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(reso_fname))
1122 : :
1123 [ - + ]: 1 : if (BS_files%in_hcoup /= BSE_NOFILE) then
1124 : 0 : coup_fname = BS_files%in_hcoup
1125 : : else
1126 : 1 : coup_fname = BS_files%out_hcoup
1127 : : end if
1128 [ + - ]: 1 : call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(coup_fname))
1129 : :
1130 : : ! TODO: Reintegrate SCALAPACK: use new format
1131 : : ! --- !ERROR
1132 : : ! src_file: m_exc_diago.F90
1133 : : ! src_line: 1398
1134 : : ! mpi_rank: 0
1135 : : ! message: |
1136 : : ! SET_VIEW
1137 : : ! Other I/O error , error stack:
1138 : : ! ADIO_Set_view(48): **iobadoverlap displacements of filetype must be in a monotonically nondecreasing order
1139 : : ! ...
1140 : :
1141 : 1 : use_scalapack = .FALSE.
1142 : : #ifdef HAVE_LINALG_SCALAPACK
1143 : : ! This is alway false. I use this trick so that the second case below is always compiled
1144 : : ! to avoid regressions.
1145 : : use_scalapack = nprocs > 1 .and. nsppol > 5
1146 : : #endif
1147 : : !use_scalapack = .FALSE.
1148 : : !use_scalapack = .TRUE.
1149 : :
1150 [ - + ]: 1 : if (.not.use_scalapack .and. my_rank/=master) GOTO 10
1151 : :
1152 [ - + + - : 3 : ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
+ - + - +
- - + -
+ ]
1153 : :
1154 : : SELECT CASE (use_scalapack)
1155 : :
1156 : : CASE (.FALSE.)
1157 : 1 : write(msg,'(a)')". Using LAPACK sequential version to solve FHv = ev with H positive definite. "
1158 [ + + ]: 3 : call wrtout([std_out, ab_out], msg)
1159 : :
1160 : 1 : bsize_ham = 2*dp*exc_size**2
1161 : 1 : write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',2*bsize_ham*b2Gb,' Gb. '
1162 : 1 : call wrtout(std_out, msg)
1163 : :
1164 [ - + + - : 4 : ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
- + + - +
- + - + -
- + - + ]
1165 [ - + + - : 3 : ABI_MALLOC_OR_DIE(fmat,(exc_size,exc_size), ierr)
- + + - +
- - + -
+ ]
1166 : :
1167 : : write(msg,'(3a,f8.1,3a,f8.1,a)')&
1168 : 1 : ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
1169 : 1 : ' Memory-space requested: ',2*dp*exc_size*b2Gb,' Gb. ',ch10,&
1170 : 2 : ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
1171 : 1 : call wrtout(std_out, msg)
1172 : :
1173 [ - + ]: 1 : if (open_file(reso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
1174 : 0 : ABI_ERROR(msg)
1175 : : end if
1176 : : !
1177 : : ! Read the header and perform consistency checks.
1178 : 1 : call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
1179 [ - + ]: 1 : ABI_CHECK(ierr==0,"Wrong header")
1180 : : !
1181 : : ! Construct Hbar = ( R C )
1182 : : ! ( C* R*)
1183 : : !
1184 : 1 : row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene)
1185 : 1 : call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
1186 : 1 : close(hreso_unt)
1187 : :
1188 [ - + ]: 1 : if (open_file(coup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
1189 : 0 : ABI_ERROR(msg)
1190 : : end if
1191 : : !
1192 : : ! Read the header and perform consistency checks.
1193 : 1 : call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
1194 [ - + ]: 1 : ABI_CHECK(ierr==0,"Wrong header")
1195 : :
1196 : 1 : row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here.
1197 : 1 : call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
1198 : 1 : close(hcoup_unt)
1199 : :
1200 : : !#ifdef DEV_MG_DEBUG_THIS
1201 : : !write(666)exc_ham
1202 : : !#endif
1203 : : !
1204 : : ! Fill fmat = (1 0)
1205 : : ! (0 -1)
1206 [ + + + + ]: 590593 : fmat = czero
1207 [ + + ]: 2 : do spin=1,nsppol
1208 : 1 : pad_r1 = (spin-1)*Bsp%nreh(1)
1209 [ + + ]: 2 : pad_r2 = SUM(Bsp%nreh)
1210 [ - + ]: 1 : if (spin==2) pad_r2 = pad_r2 + Bsp%nreh(1)
1211 [ + + ]: 386 : do it=1,Bsp%nreh(spin)
1212 : 384 : row1 = it + pad_r1
1213 : 384 : row2 = it + pad_r2
1214 : 384 : fmat(row1,row1) = cone
1215 : 385 : fmat(row2,row2) = -cone
1216 : : end do
1217 : : end do
1218 : : !
1219 : : ! ==================================================
1220 : : ! ==== Solve generalized EV problem F H u = e u ====
1221 : : ! ==================================================
1222 : : ! The eigenvectors Z are normalized as follows: if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, Z**T*inv(B)*Z = I.
1223 : : !
1224 : 1 : itype=2
1225 [ + - ]: 1 : if (do_full_diago) then
1226 : 1 : call wrtout(std_out," Full diagonalization with XHEGV... ")
1227 : 1 : call xhegv(itype,"Vectors","Upper",exc_size,fmat,exc_ham,exc_ene)
1228 : : else
1229 : 0 : call wrtout(std_out," Partial diagonalization with XHEGVX... ")
1230 [ # # # # : 0 : ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,nstates), ierr)
# # # # #
# # # # #
# # # # ]
1231 : 0 : il=1; iu=1; abstol=zero
1232 : 0 : call xhegvx(itype,"Vectors","All","Upper",exc_size,fmat,exc_ham,vl,vu,il,iu,abstol,neig_found,exc_ene,exc_rvect,exc_size)
1233 : : end if
1234 : :
1235 [ - + ]: 1 : ABI_FREE(exc_ham)
1236 : :
1237 [ + - ]: 1 : if (do_full_diago) then
1238 [ - + + - : 4 : ABI_MALLOC(exc_rvect,(exc_size,nstates))
- + + - +
- + - - +
- + - + ]
1239 [ - + + + : 590594 : exc_rvect = fmat(:,1:nstates)
+ + ]
1240 : : end if
1241 : :
1242 [ - + ]: 1 : ABI_FREE(fmat)
1243 : :
1244 [ + - ]: 1 : call wrtout(std_out," Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
1245 : :
1246 [ - + ]: 1 : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
1247 : 0 : ABI_ERROR(msg)
1248 : : end if
1249 : :
1250 : 1 : do_ep_lifetime = .FALSE.
1251 : 1 : write(eig_unt) do_ep_lifetime
1252 : 1 : write(eig_unt) exc_size, nstates
1253 [ + + ]: 769 : write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dp)
1254 [ + + ]: 769 : do mi=1,nstates
1255 [ + + ]: 590593 : write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dp)
1256 : : end do
1257 : :
1258 : : !#ifdef DEV_MG_DEBUG_THIS
1259 : : ! write(888)exc_rvect
1260 : : ! write(888)exc_ene
1261 : : !#endif
1262 : :
1263 [ - + + - : 4 : ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
- + + - +
- + - + -
- + - + ]
1264 : :
1265 : 1 : call wrtout(std_out,' Calculating overlap matrix...')
1266 : :
1267 : 1 : call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
1268 [ - + ]: 1 : ABI_FREE(exc_rvect)
1269 : :
1270 : : !#ifdef DEV_MG_DEBUG_THIS
1271 : : !write(667)ovlp
1272 : : !#endif
1273 : :
1274 : 1 : call wrtout(std_out," Inverting overlap matrix... ")
1275 : : !
1276 : : ! The overlap is Hermitian definite positive.
1277 : 1 : call xhdp_invert("Upper",ovlp,nstates)
1278 : 1 : call hermitianize(ovlp,"Upper")
1279 : :
1280 : : ! Version for generic complex matrix.
1281 : : !call xginv(ovlp,nstates)
1282 : :
1283 : : !#ifdef DEV_MG_DEBUG_THIS
1284 : : !write(668,*)ovlp
1285 : : !#endif
1286 : :
1287 [ + - ]: 1 : call wrtout(std_out,' Writing overlap matrix O^-1 on file: '//TRIM(bseig_fname))
1288 [ + + ]: 769 : do it=1,nstates
1289 : 769 : write(eig_unt) ovlp(:,it)
1290 : : end do
1291 : :
1292 [ - + ]: 1 : ABI_FREE(ovlp)
1293 : 3 : close(eig_unt)
1294 : :
1295 : : CASE (.TRUE.)
1296 : :
1297 : : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
1298 : : !
1299 : : ! Init scaLAPACK matrix Hbar = ( R C )
1300 : : ! ( C* R*)
1301 : : ! Battle plan:
1302 : : ! Here the reading is complicated by the fact that R and C are stored on two different files
1303 : : ! and moreover the matrices are in packed storage mode.
1304 : : ! For initializing the local part of the resonant and anti-resonant block we have to allocate
1305 : : ! a temporary buffer. Then we read the buffer from file and the corresponding elements of the
1306 : : ! scaLAPACK matrix are initialized taking into account the symmetries of R (Hermitian)
1307 : : ! The same procedure is used to read the coupling and the anti-coupling part (Symmetric).
1308 : : !
1309 : : tbloc=50
1310 : : write(msg,'(2(a,i0))')". Using MPI-IO + scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
1311 : : call wrtout([std_out, ab_out], msg, do_flush=.True.)
1312 : : !
1313 : : ! Init scaLAPACK environment.
1314 : : call Slk_processor%init(comm)
1315 : : !
1316 : : ! Open the Resonant file with MPI-IO and skip the record.
1317 : : amode=MPI_MODE_RDONLY
1318 : :
1319 : : call MPI_FILE_OPEN(comm, reso_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1320 : : msg = " MPI_IO error opening file: "//TRIM(reso_fname)
1321 : : ABI_CHECK_MPI(mpi_err,msg)
1322 : : !
1323 : : ! Skip the header and find the offset for reading the matrix.
1324 : : call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
1325 : : !
1326 : : ! Read = ( R - )
1327 : : ! ( - R*)
1328 : : call Slk_Hbar%init(exc_size,exc_size,Slk_processor,istwfk1)
1329 : :
1330 : : nullify(myel2loc)
1331 : : nsblocks=nsppol
1332 : : ABI_MALLOC(sub_block,(2,2,nsblocks))
1333 : : ABI_CHECK(nsppol==1,"nsppol==2 not coded yet")
1334 : :
1335 : : call slk_single_fview_read_mask(Slk_Hbar,rrs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
1336 : : & offset_err,is_fortran_file)
1337 : :
1338 : : if (offset_err/=0) then
1339 : : write(msg,"(3a)")&
1340 : : & " Global position index cannot be stored in a standard Fortran integer ",ch10,&
1341 : : & " Excitonic matrix cannot be read with a single MPI-IO call."
1342 : : ABI_ERROR(msg)
1343 : : end if
1344 : :
1345 : : ! Shift the offset because the view starts at the fist matrix element!
1346 : : ! TODO should rationalize the treatment of the offset
1347 : : my_offset = ehdr_offset + xmpio_bsize_frm
1348 : : call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
1349 : : ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1350 : :
1351 : : call MPI_TYPE_FREE(slk_mask_type,mpi_err)
1352 : : ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1353 : : !
1354 : : ! Read my portion of the R,-R* sublocks and store the values in a temporary buffer.
1355 : : ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
1356 : :
1357 : : call xmpi_barrier(comm)
1358 : :
1359 : : call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1360 : : ABI_CHECK_MPI(mpi_err,"READ_ALL")
1361 : : !
1362 : : ! Symmetrize my Resonant part.
1363 : : do el=1,my_nel
1364 : : iloc = myel2loc(1,el)
1365 : : jloc = myel2loc(2,el)
1366 : : call Slk_Hbar%loc2glob(iloc,jloc,iglob,jglob)
1367 : : ctmp = tmp_cbuffer(el)
1368 : : if (iglob==jglob.and..not.Bsp%have_complex_ene) ctmp = DBLE(ctmp) ! Force the diagonal to be real.
1369 : : rrs_kind = rrs_of_glob(iglob,jglob,Slk_Hbar%size_global)
1370 : : if (rrs_kind==1.and.jglob<iglob) then ! Lower resonant
1371 : : ctmp = DCONJG(ctmp)
1372 : : else if (rrs_kind==-1.and.jglob>=iglob) then ! Lower Anti-resonant (Diagonal is included).
1373 : : ctmp = DCONJG(ctmp)
1374 : : end if
1375 : : Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
1376 : : end do
1377 : :
1378 : : ABI_FREE(tmp_cbuffer)
1379 : : ABI_FREE(myel2loc)
1380 : :
1381 : : call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1382 : : ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1383 : : !
1384 : : ! Read = ( - C)
1385 : : ! (-C* -)
1386 : : !
1387 : : call MPI_FILE_OPEN(comm, coup_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1388 : : msg = " MPI_IO error opening file: "//TRIM(coup_fname)
1389 : : ABI_CHECK_MPI(mpi_err,msg)
1390 : : !
1391 : : ! Skip the header and find the offset for reading the matrix.
1392 : : call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
1393 : :
1394 : : nullify(myel2loc)
1395 : : call slk_single_fview_read_mask(Slk_Hbar,ccs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
1396 : : & offset_err,is_fortran_file)
1397 : :
1398 : : ABI_FREE(sub_block)
1399 : :
1400 : : if (offset_err/=0) then
1401 : : write(msg,"(3a)")&
1402 : : & " Global position index cannot be stored in a standard Fortran integer ",ch10,&
1403 : : & " Excitonic matrix cannot be read with a single MPI-IO call."
1404 : : ABI_ERROR(msg)
1405 : : end if
1406 : : !
1407 : : ! Shift the offset because the view starts at the fist matrix element!
1408 : : ! TODO should rationalize the treatment of the offset so that the client code
1409 : : ! will automatically receive my_offset.
1410 : : my_offset = ehdr_offset + xmpio_bsize_frm
1411 : : call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
1412 : : ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1413 : :
1414 : : call MPI_TYPE_FREE(slk_mask_type,mpi_err)
1415 : : ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1416 : : !
1417 : : ! Read my portion of the C-C* blocks and store the values in a temporary buffer.
1418 : : ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
1419 : :
1420 : : call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1421 : : ABI_CHECK_MPI(mpi_err,"READ_ALL")
1422 : : !
1423 : : ! Symmetrize my coupling part.
1424 : : ! Coupling block is symmetric => No symmetrization of the lower triangle.
1425 : : do el=1,my_nel
1426 : : iloc = myel2loc(1,el)
1427 : : jloc = myel2loc(2,el)
1428 : : call Slk_Hbar%loc2glob(iloc, jloc, iglob, jglob)
1429 : : ccs_kind = ccs_of_glob(iglob,jglob,Slk_Hbar%size_global)
1430 : : ctmp = tmp_cbuffer(el)
1431 : : if (ccs_kind==-1) ctmp = DCONJG(ctmp) ! Anti-coupling (Diagonal is included).
1432 : : Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
1433 : : end do
1434 : :
1435 : : ABI_FREE(tmp_cbuffer)
1436 : : ABI_FREE(myel2loc)
1437 : :
1438 : : !max_r=20; max_c=10
1439 : : !call print_arr(Slk_Hbar%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
1440 : :
1441 : : !#ifdef DEV_MG_DEBUG_THIS
1442 : : ! ABI_MALLOC(exc_ham,(exc_size,exc_size))
1443 : : ! read(666)exc_ham
1444 : : !
1445 : : ! write(std_out,*)"Error Hbar: ",MAXVAL(ABS(exc_ham-Slk_Hbar%buffer_cplx))
1446 : : ! ABI_FREE(exc_ham)
1447 : : !#endif
1448 : :
1449 : : call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1450 : : ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1451 : : !
1452 : : ! Init scaLAPACK matrix F
1453 : : call Slk_F%init(exc_size,exc_size,Slk_processor,istwfk1)
1454 : : !
1455 : : ! Global F = (1 0)
1456 : : ! (0 -1)
1457 : : do jloc=1,Slk_F%size_local(2)
1458 : : do iloc=1,Slk_F%size_local(1)
1459 : : call Slk_F%loc2glob(iloc, jloc, iglob, jglob)
1460 : : if (iglob==jglob) then
1461 : : if (iglob<=SUM(Bsp%nreh)) then
1462 : : Slk_F%buffer_cplx(iloc,jloc) = cone
1463 : : else
1464 : : Slk_F%buffer_cplx(iloc,jloc) = -cone
1465 : : end if
1466 : : else
1467 : : Slk_F%buffer_cplx(iloc,jloc) = czero
1468 : : end if
1469 : : end do
1470 : : end do
1471 : : !
1472 : : ! ===========================================================
1473 : : ! ==== Solve generalized EV problem H u = F Hbar u = e u ====
1474 : : ! ===========================================================
1475 : : call Slk_vec%init(exc_size,exc_size,Slk_processor,istwfk1)
1476 : : !
1477 : : itype=2; vl=1; vu=1; il=1; iu=nstates
1478 : : abstol=zero !ABSTOL = PDLAMCH(comm,'U')
1479 : :
1480 : : !#if 1
1481 : : if (do_full_diago) then
1482 : : call slk_F%pzhegvx(itype,"Vectors","All","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
1483 : : else
1484 : : ABI_WARNING("Partial diago is still under testing")
1485 : : call slk_F%pzhegvx(itype,"Vectors","Index","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
1486 : : end if
1487 : : !#else
1488 : : ! call xhegv(itype,"Vectors","Upper",exc_size,Slk_F%buffer_cplx,Slk_Hbar%buffer_cplx,exc_ene)
1489 : : ! Slk_vec%buffer_cplx = Slk_F%buffer_cplx
1490 : : !#endif
1491 : :
1492 : : !#ifdef DEV_MG_DEBUG_THIS
1493 : : ! if (PRODUCT(Slk_Hbar%size_local) /= exc_size**2) then
1494 : : ! ABI_ERROR("Wrong size")
1495 : : ! end if
1496 : : !
1497 : : ! ABI_MALLOC(exc_ham,(exc_size,exc_size))
1498 : : ! read(888)exc_ham
1499 : : !
1500 : : ! write(std_out,*)"Error rvec: ",MAXVAL(ABS(exc_ham-Slk_vec%buffer_cplx))
1501 : : ! ABI_FREE(exc_ham)
1502 : : !
1503 : : ! ABI_MALLOC(test_ene,(exc_size))
1504 : : ! read(888)test_ene
1505 : : ! write(std_out,*)"Error ene: ",MAXVAL(ABS(exc_ene-test_ene))
1506 : : ! ABI_FREE(test_ene)
1507 : : !#endif
1508 : :
1509 : : call Slk_F%free()
1510 : : call Slk_Hbar%free()
1511 : :
1512 : : call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
1513 : : !
1514 : : ! Open the file with Fortran-IO to write the Header.
1515 : : if (my_rank==master) then
1516 : : if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
1517 : : ABI_ERROR(msg)
1518 : : end if
1519 : :
1520 : : write(eig_unt) exc_size,nstates
1521 : : write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dp)
1522 : : !do mi=1,exc_size
1523 : : ! write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dp)
1524 : : !end do
1525 : : close(eig_unt)
1526 : : end if
1527 : : !
1528 : : ! Open the file with MPI-IO and write the distributed eigevectors.
1529 : : call xmpi_barrier(comm)
1530 : : amode=MPI_MODE_RDWR
1531 : : call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1532 : : ABI_CHECK_MPI(mpi_err,"FILE_OPEN: "//TRIM(bseig_fname))
1533 : : !
1534 : : ! Skip the header and find the offset for writing the matrix.
1535 : : ehdr_offset=0
1536 : : !call hdr_mpio_skip(mpi_fh,fform,ehdr_offset)
1537 : :
1538 : : call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
1539 : : write(std_out,*)" fmarker1 = ",fmarker
1540 : : call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
1541 : : write(std_out,*)" fmarker2 = ",fmarker
1542 : :
1543 : : write(std_out,*)" Writing nstates ",nstates
1544 : : gsub(:,1) = (/1,1/)
1545 : : gsub(:,2) = (/exc_size,nstates/)
1546 : : call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
1547 : :
1548 : : call wrtout(std_out,' Calculating overlap matrix... ')
1549 : : if (.not.do_full_diago) then
1550 : : ABI_ERROR(" Init of Slk_ovlp is wrong")
1551 : : end if
1552 : :
1553 : : call Slk_ovlp%init(exc_size,exc_size,Slk_processor,istwfk1)
1554 : :
1555 : : ! Calculate the overlap matrix.
1556 : : ! FIXME
1557 : : ! The ESLL manual says that "matrices matrix1 and matrix2 must have no common elements;
1558 : : ! otherwise, results are unpredictable."
1559 : : ! However the official scaLAPACK documentation does not report this (severe) limitation.
1560 : :
1561 : : !call Slk_tmp%init(exc_size,exc_size,Slk_processor,istwfk1)
1562 : : !Slk_tmp%buffer_cplx = Slk_vec%buffer_cplx
1563 : : !call slk_pgemm("C","N",Slk_tmp,cone,Slk_vec,czero,Slk_ovlp)
1564 : : !call Slk_tmp%free()
1565 : :
1566 : : call slk_pgemm("C","N",Slk_vec,cone,Slk_vec,czero,Slk_ovlp)
1567 : :
1568 : : !#ifdef DEV_MG_DEBUG_THIS
1569 : : ! ABI_MALLOC(exc_ham,(exc_size,exc_size))
1570 : : ! read(667)exc_ham
1571 : : !
1572 : : ! write(std_out,*)"Error Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
1573 : : ! !Slk_ovlp%buffer_cplx = exc_ham
1574 : : !#endif
1575 : :
1576 : : !max_r=20; max_c=10
1577 : : !call print_arr(Slk_ovlp%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
1578 : :
1579 : : call Slk_vec%free()
1580 : :
1581 : : call wrtout(std_out," Inverting overlap matrix... ")
1582 : : uplo="Upper"
1583 : :
1584 : : !#if 0
1585 : : !!DEBUG
1586 : : ! call xhdp_invert(uplo,Slk_ovlp%buffer_cplx,exc_size)
1587 : : !
1588 : : ! !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
1589 : : ! call hermitianize(Slk_ovlp%buffer_cplx,uplo)
1590 : : !
1591 : : ! exc_ham = MATMUL(exc_ham,Slk_ovlp%buffer_cplx)
1592 : : ! do it=1,exc_size
1593 : : ! exc_ham(it,it) = exc_ham(it,it) - cone
1594 : : ! end do
1595 : : !
1596 : : ! write(std_out,*)"Error Inversion: ",MAXVAL(ABS(exc_ham))
1597 : : ! ABI_FREE(exc_ham)
1598 : : !!END DEBUG
1599 : : !
1600 : : !#else
1601 : : ! call Slk_ovlp%hpd_invert(uplo)
1602 : : ! call hermitianize(Slk_ovlp%buffer_cplx,uplo)
1603 : : ! !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
1604 : :
1605 : : call Slk_ovlp%invert() ! Version for generic complex matrix.
1606 : : !#endif
1607 : :
1608 : : !#ifdef DEV_MG_DEBUG_THIS
1609 : : ! ABI_MALLOC(exc_ham,(exc_size,exc_size))
1610 : : ! read(668)exc_ham
1611 : : ! write(std_out,*)"Error in Inv Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
1612 : : !
1613 : : ! !exc_ham = exc_ham-Slk_ovlp%buffer_cplx
1614 : : ! !do it=1,exc_size
1615 : : ! ! if ( MAXVAL(ABS(exc_ham(:,it))) > 0.1 ) write(std_out,*)"it: ",it,exc_ham(:,it)
1616 : : ! !end do
1617 : : !
1618 : : ! !Slk_ovlp%buffer_cplx = exc_ham
1619 : : ! ABI_FREE(exc_ham)
1620 : : !
1621 : : ! !write(std_out,*)"MAX ERR",MAXVAL(ABS(Slk_ovlp%buffer_cplx - TRANSPOSE(DCONJG(Slk_ovlp%buffer_cplx))))
1622 : : !#endif
1623 : :
1624 : : call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
1625 : :
1626 : : call slk_write(Slk_ovlp,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
1627 : :
1628 : : call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1629 : : ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1630 : :
1631 : : call Slk_ovlp%free()
1632 : : call Slk_processor%free()
1633 : : #else
1634 : : ABI_BUG("You should not be here!")
1635 : : #endif
1636 : :
1637 : : END SELECT
1638 : :
1639 [ + - - + : 770 : exc_gap = MINVAL(ABS(exc_ene(1:nstates)))
- - + + ]
1640 [ + - - + : 770 : exc_maxene = MAXVAL(ABS(exc_ene(1:nstates)))
- - + + ]
1641 : :
1642 : : write(msg,'(2(a,f7.2,2a))')&
1643 : 1 : " First excitonic eigenvalue: ",exc_gap*Ha_eV, " [eV].",ch10,&
1644 : 2 : " Last excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10
1645 [ + + ]: 3 : call wrtout([std_out, ab_out], msg)
1646 : :
1647 [ - + ]: 1 : nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
1648 : 1 : write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
1649 : 1 : call wrtout(std_out, msg)
1650 : :
1651 [ + + ]: 9 : do it=0,(nene_printed-1)/4
1652 [ + - + + ]: 40 : write(msg,'(4f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
1653 : 9 : call wrtout(std_out, msg)
1654 : : end do
1655 : :
1656 [ - + ]: 1 : ABI_FREE(exc_ene)
1657 : :
1658 : 1 : 10 call xmpi_barrier(comm)
1659 : :
1660 [ - + ]: 1 : end subroutine exc_diago_coupling_hegv
1661 : : !!***
1662 : :
1663 : : !----------------------------------------------------------------------
1664 : :
1665 : : end module m_exc_diago
1666 : : !!***
|