Line data Source code
1 : !!****m* ABINIT/m_exc_build
2 : !! NAME
3 : !! m_exc_build
4 : !!
5 : !! FUNCTION
6 : !! Build the BSE Hamiltonian in the e-h representation with MPI
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 1992-2009 EXC group (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida)
10 : !! Copyright (C) 2009-2026 ABINIT group (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_exc_build
24 :
25 : use defs_basis
26 : use m_abicore
27 : use m_bs_defs
28 : use m_bse_io
29 : USE_MPI
30 : use m_xmpi
31 : use m_errors
32 : use m_screen
33 : use m_hdr
34 :
35 : use m_wfd, only : wfdgw_t, wave_t, WFD_STORED
36 : use defs_datatypes, only : pseudopotential_type
37 : use m_gwdefs, only : czero_gw, cone_gw, GW_TOLQ0
38 : use m_time, only : cwtime, timab
39 : use m_io_tools, only : get_unit, open_file
40 : use m_hide_blas, only : xdotc, xgemv
41 : use m_geometry, only : normv
42 : use m_crystal, only : crystal_t
43 : use m_gsphere, only : gsphere_t
44 : use m_vcoul, only : vcoul_t
45 : use m_bz_mesh, only : kmesh_t, findqg0
46 : use m_pawpwij, only : pawpwff_t, pawpwij_t, pawpwij_init, pawpwij_free, paw_rho_tw_g
47 : use m_pawang, only : pawang_type
48 : use m_pawtab, only : pawtab_type
49 : use m_pawcprj, only : pawcprj_type, pawcprj_alloc, pawcprj_free
50 : use m_paw_sym, only : paw_symcprj_op
51 : use m_oscillators, only : rho_tw_g, sym_rhotwgq0
52 :
53 : implicit none
54 :
55 : #if defined HAVE_MPI1
56 : include 'mpif.h'
57 : #endif
58 :
59 : private
60 : !!***
61 :
62 : public :: exc_build_ham ! Calculate and write the excitonic Hamiltonian to file.
63 : !!***
64 :
65 : contains
66 : !!***
67 :
68 : !!****f* m_exc_build/exc_build_block
69 : !! NAME
70 : !! exc_build_block
71 : !!
72 : !! FUNCTION
73 : !! Calculate and write the excitonic Hamiltonian on an external binary file (Fortran file open
74 : !! in random mode) for subsequent treatment in the Bethe-Salpeter code.
75 : !!
76 : !! INPUTS
77 : !! BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
78 : !! Cryst<crystal_t>=Info on the crystalline structure.
79 : !! Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
80 : !! Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
81 : !! ktabr(nfftot_osc,BSp%nkbz)=The FFT index of $(R^{-1}(r-\tau))$ where R is symmetry needed to obtains
82 : !! the k-points from the irreducible image. Used to symmetrize u_Sk where S = \transpose R^{-1}
83 : !! Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
84 : !! Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
85 : !! Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
86 : !! screen<screen_t>=Data type gathering info and data for W.
87 : !! nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
88 : !! ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
89 : !! Psps<Pseudopotential_type>=Variables related to pseudopotentials
90 : !! Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
91 : !! Pawang<pawang_type>=PAW angular mesh and related data.
92 : !! Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite matrix
93 : !! elements of a plane wave.
94 : !! Wfd<wfdgw_t>=Handler for the wavefunctions.
95 : !! prtvol=Verbosity level.
96 : !! rhxtwg_q0
97 : !! is_resonant
98 : !! fname
99 : !! comm=MPI communicator.
100 : !!
101 : !! OUTPUT
102 : !! The excitonic Hamiltonian is saved on an external binary file (see below).
103 : !!
104 : !! NOTES
105 : !! *) Version for K_V = K_C (q=0), thus KP_V = KP_C
106 : !! *) No exchange limit: use DFT energies in case.
107 : !! *) Symmetry of H(-k-k') = H*(k k') not used.
108 : !! *) Coulomb term can be approximated as diagonal in G.
109 : !! *) Valence bands treated from lomo on.
110 : !! *) Symmetries of the sub-blocks are used to reduce the number of elements to calculate.
111 : !!
112 : !! ____________
113 : !! |_(cv)__(vc)_|
114 : !! H_exc = | R C |
115 : !! | -C* -R* |
116 : !!
117 : !! where C is symmetric and R is Hermitian provided that the QP energies are real.
118 : !!
119 : !! For nsppol=1 ==> R = diag-W+2v; C = -W+2v
120 : !! since the Hamiltonian can be diagonalized in the spin-singlet basis set thanks to
121 : !! the fact that spin triplet does not contribute to the optical limit of epsilon.
122 : !!
123 : !! For nsppol=2 ==> R = diag-W+v; C = -W+v
124 : !! Now the matrix elements depend on the spin of the transitions but only those
125 : !! transitions in which the spin of the electron and of the hole are equal contribute
126 : !! to the macroscopic dielectric function. Moreover only the exchange term can connect transitions of different spin.
127 : !! When nsppol==2 the transitions are ordered using | (cv up) | (cv dwn) | (vc up) | (vc down) |
128 : !!
129 : !! The resonant block is given by:
130 : !!
131 : !! | (v'c' up) | (v'c' dwn) |
132 : !! ----------------------------------- where v_{-+} = v_{+-}^H when the momentum of the photon is neglected.
133 : !! | [diag-W+v]++ | v+- | (vc up) Note that v_{+-} is not Hermitian due to the presence of different spins.
134 : !! R = ----------------------------------- Actually it reduces to a Hermitian matrix when the system is not spin polarized.
135 : !! | v-+ | [diag-W+v]-- | (vc dwn) but in this case one should use nsppol=1.
136 : !! ----------------------------------- As a consequence the entire matrix is calculated and stored on file.
137 : !!
138 : !! The coupling block is given by:
139 : !!
140 : !! | (c'v' up) | (c'v dwn) |
141 : !! ----------------------------------- where v_{-+} = v_{+-}^t when the momentum of the photon is neglected.
142 : !! | [-W+v]++ | v+- | (vc up) Also in this case the entire matrix v_{+-} has to be calculated
143 : !! C = ----------------------------------- and stored on file.
144 : !! | v-+ | [-W+v]-- | (vc dwn)
145 : !! -----------------------------------
146 : !!
147 : !! SOURCE
148 :
149 23 : subroutine exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,Wfd,screen,Hdr_bse,&
150 23 : nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,rhxtwg_q0,is_resonant,fname)
151 :
152 : !Arguments ------------------------------------
153 : !scalars
154 : integer,intent(in) :: nfftot_osc
155 : character(len=*),intent(in) :: fname
156 : logical,intent(in) :: is_resonant
157 : type(excparam),intent(in) :: BSp
158 : type(screen_t),intent(inout) :: screen
159 : type(kmesh_t),intent(in) :: Kmesh,Qmesh
160 : type(crystal_t),intent(in) :: Cryst
161 : type(vcoul_t),intent(in) :: Vcp
162 : type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
163 : type(Pseudopotential_type),intent(in) :: Psps
164 : type(Hdr_type),intent(inout) :: Hdr_bse
165 : type(pawang_type),intent(in) :: Pawang
166 : type(wfdgw_t),target,intent(inout) :: Wfd
167 : !arrays
168 : integer,intent(in) :: ngfft_osc(18)
169 : integer,intent(in) :: ktabr(nfftot_osc,Kmesh%nbz)
170 : complex(gwp),intent(in) :: rhxtwg_q0(BSp%npweps,BSp%lomo_min:BSp%humo_max,BSp%lomo_min:BSp%humo_max,Wfd%nkibz,Wfd%nsppol)
171 : type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat*Wfd%usepaw)
172 : type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
173 :
174 : !Local variables ------------------------------
175 : !scalars
176 : integer,parameter :: map2sphere=1,ndat1=1,master=0
177 : integer(i8b) :: bsize_my_block
178 : integer :: nspinor,nsppol,ISg,mpi_err,tmp_size,ngx
179 : integer :: ik_bz,ikp_bz,col_glob,itpk_min,itpk_max
180 : integer :: dim_rtwg,bsh_unt,ncol,dump_unt,npweps
181 : #ifdef HAVE_MPI_IO
182 : integer :: amode,mpi_fh,hmat_type,offset_err,old_type
183 : integer(XMPI_OFFSET_KIND) :: ehdr_offset,my_offset
184 : logical,parameter :: is_fortran_file=.TRUE.
185 : #endif
186 : integer :: neh1,neh2,ig,nblocks
187 : integer :: ik_ibz,itim_k,ikp_ibz,itim_kp,isym_k,isym_kp
188 : integer :: iq_bz,iq_ibz,isym_q,itim_q,iqbz0,rank
189 : integer :: iv,ivp,ic,icp,jj,nrows,sender,my_ncols
190 : integer :: use_padfft,prev_nrows,spin1,spin2,block
191 : integer :: ierr,nproc,my_rank,mgfft_osc,fftalga_osc,comm
192 : integer(i8b) :: tot_nels,prev_nels,prev_ncols,nels,ir,it,itp,ist,iend,my_hsize
193 : real(dp) :: faq,kx_fact,cputime,walltime,gflops
194 : complex(sp) :: http,ctemp
195 : complex(dp) :: ph_mkpt,ph_mkt,ene_t,ene_tp
196 : logical,parameter :: with_umklp=.FALSE.
197 : logical :: use_mpiio,do_coulomb_term,do_exchange_term,w_is_diagonal,isirred
198 : logical :: is_qeq0
199 : character(len=500) :: msg
200 : type(wave_t),pointer :: wave_ck, wave_ckp, wave_vk, wave_vkp
201 : !arrays
202 : integer :: bidx(2,4),g0(3),spin_ids(2,3)
203 : integer(i8b) :: nels_block(3)
204 : integer :: my_cols(2),my_rows(2),proc_end(2),proc_start(2)
205 : integer :: my_extrema(2,2),sender_extrema(2,2),my_starts(2),my_ends(2)
206 23 : integer,allocatable :: igfftg0(:),ktabr_k(:),ktabr_kp(:),id_tab(:)
207 23 : integer,allocatable :: ncols_of(:)
208 23 : integer(i8b),allocatable :: t_start(:),t_stop(:),hsize_of(:)
209 23 : integer,allocatable :: col_start(:),col_stop(:)
210 23 : integer,allocatable :: gbound(:,:)
211 : real(dp) :: kbz(3),kpbz(3),qbz(3),spinrot_k(4),spinrot_kp(4),kmkp(3),tsec(2)
212 23 : complex(dp),allocatable :: my_bsham(:),buffer(:),buffer_2d(:,:),my_kxssp(:,:),prev_col(:)
213 : !DBYG
214 23 : complex(dp),allocatable :: acoeffs(:),bcoeffs(:),ccoeffs(:) ! Coeff of W = a/q^2 + b/q + c
215 : integer :: a_unt, b_unt, c_unt
216 : complex(dp) :: aatmp, bbtmp, cctmp
217 23 : complex(gwp),allocatable :: aa_vpv(:),aa_cpc(:),aa_ctccp(:)
218 23 : complex(gwp),allocatable :: bb_vpv1(:),bb_cpc1(:),bb_ctccp1(:)
219 23 : complex(gwp),allocatable :: bb_vpv2(:),bb_cpc2(:),bb_ctccp2(:)
220 23 : complex(gwp),allocatable :: cc_vpv(:),cc_cpc(:),cc_ctccp(:)
221 23 : complex(dp),allocatable :: abuffer(:),aprev_col(:)
222 23 : complex(dp),allocatable :: bbuffer(:),bprev_col(:)
223 23 : complex(dp),allocatable :: cbuffer(:),cprev_col(:)
224 : character(len=fnlen) :: tmpfname
225 : integer :: ii
226 : !END DBYG
227 23 : complex(gwp),allocatable :: vc_sqrt_qbz(:), rhotwg1(:),rhotwg2(:),rhxtwg_vpv(:),rhxtwg_cpc(:),ctccp(:)
228 23 : complex(gwp),target,allocatable :: ur_ckp(:),ur_vkp(:),ur_vk(:),ur_ck(:)
229 23 : complex(gwp),contiguous, pointer :: ptur_ckp(:),ptur_vkp(:),ptur_vk(:),ptur_ck(:)
230 23 : type(pawcprj_type),target,allocatable :: Cp_tmp1(:,:),Cp_tmp2(:,:)
231 23 : type(pawcprj_type),target,allocatable :: Cp_tmp3(:,:),Cp_tmp4(:,:)
232 23 : type(pawcprj_type),allocatable :: Cp_ckp(:,:),Cp_vkp(:,:)
233 23 : type(pawcprj_type),allocatable :: Cp_vk(:,:),Cp_ck(:,:)
234 23 : type(pawcprj_type),pointer :: ptcp_ckp(:,:),ptcp_vkp(:,:),ptcp_vk(:,:),ptcp_ck(:,:)
235 23 : type(pawpwij_t),allocatable :: Pwij_q(:)
236 : #ifdef HAVE_MPI_IO
237 : integer(XMPI_OFFSET_KIND) :: tmp_off,my_offpad
238 23 : integer(XMPI_OFFSET_KIND),allocatable :: bsize_frecord(:),offset_of_block(:)
239 : #endif
240 : #ifdef DEV_MG_DEBUG_MODE
241 : integer,allocatable :: ttp_check(:,:)
242 : #endif
243 : !************************************************************************
244 :
245 23 : call timab(680,1,tsec)
246 23 : call timab(681,1,tsec)
247 :
248 : DBG_ENTER("COLL")
249 :
250 23 : ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
251 92 : ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
252 :
253 23 : if (Wfd%nsppol==2) then
254 1 : ABI_WARNING("nsppol==2 is still under testing")
255 : end if
256 : ! MPI variables.
257 23 : comm = Wfd%comm
258 23 : nproc = Wfd%nproc
259 23 : my_rank = Wfd%my_rank
260 :
261 : ! Basic constants.
262 23 : nspinor = Wfd%nspinor
263 23 : nsppol = Wfd%nsppol
264 23 : dim_rtwg=1; faq = one/(Cryst%ucvol*Kmesh%nbz)
265 23 : npweps = Bsp%npweps
266 :
267 : ! Prepare the FFT tables to have u(r) on the ngfft_osc mesh.
268 92 : mgfft_osc = MAXVAL(ngfft_osc(1:3))
269 23 : fftalga_osc = ngfft_osc(7)/100
270 92 : if ( ANY(ngfft_osc(1:3) /= Wfd%ngfft(1:3)) ) call wfd%change_ngfft(Cryst,Psps,ngfft_osc)
271 :
272 69 : ABI_MALLOC(igfftg0,(npweps))
273 69 : ABI_MALLOC(ktabr_k,(nfftot_osc))
274 46 : ABI_MALLOC(ktabr_kp,(nfftot_osc))
275 46 : ABI_MALLOC(id_tab,(nfftot_osc))
276 482671 : id_tab = (/(ic, ic=1,nfftot_osc)/)
277 :
278 : ! Workspace arrays for wavefunctions and oscillator matrix elements.
279 69 : ABI_MALLOC(rhxtwg_vpv,(npweps))
280 46 : ABI_MALLOC(rhxtwg_cpc,(npweps))
281 :
282 23 : if (BSp%prep_interp) then
283 1 : call wrtout(std_out,"Preparing BSE interpolation")
284 2 : ABI_MALLOC(aa_vpv,(npweps))
285 2 : ABI_MALLOC(bb_vpv1,(npweps))
286 2 : ABI_MALLOC(bb_vpv2,(npweps))
287 2 : ABI_MALLOC(cc_vpv,(npweps))
288 2 : ABI_MALLOC(aa_cpc,(npweps))
289 2 : ABI_MALLOC(bb_cpc1,(npweps))
290 2 : ABI_MALLOC(bb_cpc2,(npweps))
291 2 : ABI_MALLOC(cc_cpc,(npweps))
292 : end if
293 :
294 69 : ABI_MALLOC(ur_ckp,(nspinor*nfftot_osc))
295 46 : ABI_MALLOC(ur_vkp,(nspinor*nfftot_osc))
296 46 : ABI_MALLOC(ur_ck ,(nspinor*nfftot_osc))
297 46 : ABI_MALLOC(ur_vk ,(nspinor*nfftot_osc))
298 :
299 23 : if (Wfd%usepaw==1) then
300 14 : ABI_MALLOC(Cp_vk,(Wfd%natom,nspinor))
301 2 : call pawcprj_alloc(Cp_vk,0,Wfd%nlmn_atm)
302 14 : ABI_MALLOC(Cp_ck,(Wfd%natom,nspinor))
303 2 : call pawcprj_alloc(Cp_ck,0,Wfd%nlmn_atm)
304 14 : ABI_MALLOC(Cp_ckp,(Wfd%natom,nspinor))
305 2 : call pawcprj_alloc(Cp_ckp,0,Wfd%nlmn_atm)
306 14 : ABI_MALLOC(Cp_vkp,(Wfd%natom,nspinor))
307 2 : call pawcprj_alloc(Cp_vkp,0,Wfd%nlmn_atm)
308 :
309 14 : ABI_MALLOC(Cp_tmp1,(Wfd%natom,nspinor))
310 2 : call pawcprj_alloc(Cp_tmp1,0,Wfd%nlmn_atm)
311 14 : ABI_MALLOC(Cp_tmp2,(Wfd%natom,nspinor))
312 2 : call pawcprj_alloc(Cp_tmp2,0,Wfd%nlmn_atm)
313 14 : ABI_MALLOC(Cp_tmp3,(Wfd%natom,nspinor))
314 2 : call pawcprj_alloc(Cp_tmp3,0,Wfd%nlmn_atm)
315 14 : ABI_MALLOC(Cp_tmp4,(Wfd%natom,nspinor))
316 2 : call pawcprj_alloc(Cp_tmp4,0,Wfd%nlmn_atm)
317 : end if
318 : !
319 : ! Identify the index of q==0
320 23 : iqbz0=0
321 1079 : do iq_bz=1,Qmesh%nbz
322 1446 : if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
323 : end do
324 23 : ABI_CHECK(iqbz0/=0,"q=0 not found")
325 : !
326 : ! Treat the spin polarization.
327 69 : spin_ids(:,1) = (/1,1/)
328 69 : spin_ids(:,2) = (/2,2/)
329 69 : spin_ids(:,3) = (/1,2/)
330 :
331 23 : nblocks=1
332 23 : kx_fact=two
333 23 : nels_block(:)=0
334 23 : nels_block(1)=BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2
335 23 : tot_nels=nels_block(1)
336 :
337 23 : if (nsppol==2) then
338 1 : nblocks=3
339 1 : kx_fact=one
340 : nels_block(1) = BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2 ! Only the upper triangle for block 1 and 2
341 1 : nels_block(2) = BSp%nreh(2)*(BSp%nreh(2)+1_i8b)/2
342 1 : nels_block(3) = BSp%nreh(1)*BSp%nreh(2)*1_i8b ! Note: Block 3 does not have symmetries.
343 4 : tot_nels= SUM(nels_block)
344 : end if
345 : !
346 : ! Distribute the calculation of the matrix elements among the nodes.
347 : ! * tstart and t_stop give the initial and final transition index treated by each node.
348 : ! * my_hsize is the number of transitions treated by this processor
349 : ! * my_cols(1:2) gives the initial and final column treated by this node.
350 : !
351 : use_mpiio=.FALSE.
352 : #ifdef HAVE_MPI_IO
353 : use_mpiio = (nproc>1)
354 : #endif
355 23 : use_mpiio=.FALSE.
356 : !use_mpiio=.TRUE.
357 :
358 23 : if (is_resonant) then
359 : if (use_mpiio) then
360 : write(msg,'(2a,f6.2,a)')&
361 : ". Writing resonant excitonic Hamiltonian on file "//TRIM(fname)," via MPI-IO; file size= ",two*tot_nels*dp*b2Gb," [Gb]."
362 : else
363 : write(msg,'(2a,f6.2,a)')&
364 22 : ". Writing resonant excitonic Hamiltonian on file "//TRIM(fname),"; file size= ",two*dp*tot_nels*b2Gb," [Gb]."
365 : end if
366 : else
367 : if (use_mpiio) then
368 : write(msg,'(2a,f6.2,a)')&
369 : ". Writing coupling excitonic Hamiltonian on file "//TRIM(fname)," via MPI-IO; file size= ",tot_nels*2*dp*b2Gb," [Gb]."
370 : else
371 : write(msg,'(2a,f6.2,a)')&
372 1 : ". Writing coupling excitonic Hamiltonian on file "//TRIM(fname),"; file size= ",two*dp*tot_nels*b2Gb," [Gb]."
373 : end if
374 : end if
375 69 : call wrtout([std_out, ab_out], msg, do_flush=.True.)
376 :
377 : ! Master writes the BSE header with Fortran IO.
378 23 : if (my_rank==master) then
379 19 : if (open_file(fname,msg,newunit=bsh_unt,form="unformatted",action="write") /= 0) then
380 0 : ABI_ERROR(msg)
381 : end if
382 19 : call exc_write_bshdr(bsh_unt,Bsp,Hdr_bse)
383 : ! To force the writing (needed for MPI-IO).
384 19 : close(bsh_unt)
385 :
386 19 : if (.not.use_mpiio) then ! Reopen the file and skip the header.
387 19 : if (open_file(fname,msg,newunit=bsh_unt,form="unformatted",action="readwrite") /= 0) then
388 0 : ABI_ERROR(msg)
389 : end if
390 19 : call exc_skip_bshdr(bsh_unt,ierr)
391 : end if
392 :
393 19 : if (BSp%prep_interp) then
394 1 : tmpfname = fname
395 1 : ii = LEN_TRIM(fname)
396 1 : tmpfname(ii-2:ii+1) = 'ABSR'
397 1 : if (open_file(tmpfname,msg,newunit=a_unt,form='unformatted',action="write") /= 0) then
398 0 : ABI_ERROR(msg)
399 : end if
400 1 : tmpfname(ii-2:ii+1) = 'BBSR'
401 1 : if (open_file(tmpfname,msg,newunit=b_unt,form='unformatted',action="write") /= 0) then
402 0 : ABI_ERROR(msg)
403 : end if
404 1 : tmpfname(ii-2:ii+1) = 'CBSR'
405 1 : if (open_file(tmpfname,msg,newunit=c_unt,form='unformatted',action="write") /= 0) then
406 0 : ABI_ERROR(msg)
407 : end if
408 1 : call exc_write_bshdr(a_unt,Bsp,Hdr_bse)
409 1 : call exc_write_bshdr(b_unt,Bsp,Hdr_bse)
410 1 : call exc_write_bshdr(c_unt,Bsp,Hdr_bse)
411 1 : close(a_unt)
412 1 : close(b_unt)
413 1 : close(c_unt)
414 3 : if (.not.use_mpiio) then ! Reopen the file and skip the header.
415 1 : tmpfname(ii-2:ii+1) = 'ABSR'
416 1 : if (open_file(tmpfname,msg,newunit=a_unt,form='unformatted',action="readwrite") /= 0) then
417 0 : ABI_ERROR(msg)
418 : end if
419 1 : call exc_skip_bshdr(a_unt,ierr)
420 1 : tmpfname(ii-2:ii+1) = 'BBSR'
421 1 : if (open_file(tmpfname,msg,newunit=b_unt,form='unformatted',action="readwrite") /= 0) then
422 0 : ABI_ERROR(msg)
423 : end if
424 1 : call exc_skip_bshdr(b_unt,ierr)
425 1 : tmpfname(ii-2:ii+1) = 'CBSR'
426 1 : if (open_file(tmpfname,msg,newunit=c_unt,form='unformatted',action="readwrite") /= 0) then
427 0 : ABI_ERROR(msg)
428 : end if
429 1 : call exc_skip_bshdr(c_unt,ierr)
430 : end if
431 : end if
432 : end if
433 :
434 23 : call xmpi_barrier(comm)
435 :
436 : if (use_mpiio) then
437 : #ifdef HAVE_MPI_IO
438 : ! Open the file with MPI-IO
439 : amode = MPI_MODE_RDWR
440 : !amode = MPI_MODE_CREATE + MPI_MODE_RDWR,
441 :
442 : call MPI_FILE_OPEN(comm, fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
443 : ABI_CHECK_MPI(mpi_err,"opening: "//TRIM(fname))
444 :
445 : ! Skip the header.
446 : call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
447 :
448 : ! Precompute the offset of the each block including the Fortran markers.
449 : ABI_MALLOC(offset_of_block,(nblocks))
450 : offset_of_block(1) = ehdr_offset
451 : do block=2,nblocks
452 : tmp_off = offset_of_block(block-1) + nels_block(block-1)*xmpi_bsize_dpc
453 : tmp_off = tmp_off + Bsp%nreh(block-1)*2*xmpio_bsize_frm ! markers.
454 : offset_of_block(block) = tmp_off
455 : end do
456 : #endif
457 : end if
458 :
459 23 : call timab(681,2,tsec)
460 :
461 47 : do block=1,nsppol
462 : !
463 : ! Indices used to loop over bands.
464 : ! bidx contains the starting and final indices used to loop over bands.
465 : !
466 : ! (b3,b4)
467 : ! |... ...|
468 : ! (b1,b2) |... ...|
469 : !
470 : ! Resonant matrix is given by
471 : ! (v',c')
472 : ! |... ...|
473 : ! (v,c) |... ...|
474 : !
475 : ! Coupling matrix is given by
476 : ! (c',v')
477 : ! |... ...|
478 : ! (v,c) |... ...|
479 :
480 24 : if (is_resonant) then
481 69 : bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
482 69 : bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
483 69 : bidx(:,3) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b3
484 69 : bidx(:,4) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b4
485 : else
486 3 : bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
487 3 : bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
488 3 : bidx(:,3) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b3
489 3 : bidx(:,4) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b4
490 : end if
491 :
492 24 : spin1 = spin_ids(1,block)
493 24 : spin2 = spin_ids(2,block)
494 :
495 24 : do_coulomb_term = (Bsp%use_coulomb_term .and. (spin1==spin2))
496 24 : do_exchange_term = (Bsp%exchange_term>0)
497 24 : w_is_diagonal = BSp%use_diagonal_Wgg
498 : !
499 : ! Distribution of the matrix elements among the nodes.
500 : ! Note that rank0 will get the first transitions.
501 24 : nels=nels_block(block)
502 72 : ABI_MALLOC(t_start,(0:nproc-1))
503 48 : ABI_MALLOC(t_stop,(0:nproc-1))
504 24 : call xmpi_split_work2_i8b(nels,nproc,t_start,t_stop)
505 :
506 48 : ABI_MALLOC(hsize_of,(0:nproc-1))
507 62 : hsize_of=0
508 62 : do rank=0,nproc-1
509 62 : if (t_stop(rank)>=t_start(rank)) hsize_of(rank) = t_stop(rank)-t_start(rank)+1
510 : !write(std_out,*)"nels",nels,hsize_of(rank)
511 : end do
512 :
513 24 : my_hsize = hsize_of(my_rank)
514 24 : if (my_hsize<=0) then
515 0 : write(msg,'(a,i0)')"Wrong number of transitions: my_hsize= ",my_hsize
516 0 : ABI_ERROR(msg)
517 : end if
518 24 : if (my_hsize /= INT(my_hsize,KIND=i4b)) then
519 0 : write(msg,'(a,i0)')"Size of local block too large for a default integer, Increase the number of CPUs: my_hsize= ",my_hsize
520 0 : ABI_ERROR(msg)
521 : end if
522 :
523 24 : my_cols=0
524 9272 : do itp=1,Bsp%nreh(block)
525 2182216 : do it=1,itp
526 2172944 : ir = it + itp*(itp-1_i8b)/2
527 2172944 : if (ir==t_start(my_rank)) then
528 24 : my_rows(1) = it
529 24 : my_cols(1) = itp
530 : end if
531 2182192 : if (ir==t_stop(my_rank)) then
532 24 : my_rows(2) = it
533 24 : my_cols(2) = itp
534 : end if
535 : end do
536 : end do
537 :
538 72 : my_starts = [my_rows(1),my_cols(1)]
539 24 : my_ends = [my_rows(2),my_cols(2)]
540 : !
541 : ! Announce the treatment of submatrix treated by each node.
542 24 : bsize_my_block = 2*dp*my_hsize
543 24 : write(msg,'(4(a,i0))')' Treating ',my_hsize,'/',nels,' matrix elements, from column ',my_cols(1),' up to column ',my_cols(2)
544 24 : call wrtout(std_out, msg)
545 :
546 24 : if (is_resonant) then
547 23 : write(msg,'(a,f8.1,a)')' Calculating resonant blocks. Memory required: ',bsize_my_block*b2Mb,' [Mb] <<< MEM'
548 : else
549 1 : write(msg,'(a,f8.1,a)')' Calculating coupling blocks. Memory required: ',bsize_my_block*b2Mb,' [Mb] <<< MEM'
550 : end if
551 24 : call wrtout(std_out, msg)
552 :
553 : ! Allocate big (scalable) buffer to store the BS matrix on this node.
554 72 : ABI_MALLOC_OR_DIE(my_bsham,(t_start(my_rank):t_stop(my_rank)), ierr)
555 :
556 24 : if (BSp%prep_interp) then
557 : ! Allocate big (scalable) buffers to store a,b,c coefficients
558 2 : ABI_MALLOC_OR_DIE(acoeffs,(t_start (my_rank):t_stop(my_rank)), ierr)
559 2 : ABI_MALLOC_OR_DIE(bcoeffs,(t_start(my_rank):t_stop(my_rank)), ierr)
560 2 : ABI_MALLOC_OR_DIE(ccoeffs,(t_start(my_rank):t_stop(my_rank)), ierr)
561 : end if
562 :
563 24 : if (do_coulomb_term) then ! Construct Coulomb term.
564 :
565 24 : call timab(682,1,tsec) ! exc_build_ham(Coulomb)
566 :
567 24 : write(msg,'(a,2i2,a)')" Calculating direct Coulomb term for (spin1,spin2) ",spin1,spin2," using full W_{GG'} ..."
568 24 : if (w_is_diagonal) then
569 : write(msg,'(a,2i2,a)')&
570 2 : " Calculating direct Coulomb term for (spin1, spin2) ",spin1,spin2," using diagonal approximation for W_{GG'} ..."
571 : end if
572 24 : call wrtout(std_out, msg)
573 :
574 72 : ABI_MALLOC(ctccp,(npweps))
575 :
576 24 : if (BSp%prep_interp) then
577 2 : ABI_MALLOC(aa_ctccp,(npweps))
578 2 : ABI_MALLOC(bb_ctccp1,(npweps))
579 2 : ABI_MALLOC(bb_ctccp2,(npweps))
580 2 : ABI_MALLOC(cc_ctccp,(npweps))
581 : end if
582 :
583 48 : ABI_MALLOC(vc_sqrt_qbz,(npweps))
584 :
585 : #ifdef DEV_MG_DEBUG_MODE
586 : ABI_MALLOC(ttp_check,(BSp%nreh(block),BSp%nreh(block)))
587 : ttp_check=0
588 : #endif
589 :
590 1112 : do ikp_bz=1,BSp%nkbz ! Loop over kp
591 : ! NOTE: this way of looping is good for bulk but it's not optimal in the
592 : ! case of systems sampled only at Gamma e.g. isolated systems in which
593 : ! one should take advantage of Hermiticity by looping over c-v !!!!
594 :
595 : ! Check whether (vp,cp,ikp_bz,spin2) belongs to the set of columns treated by me for some vp,cp
596 : ! Be careful since vcks2t contains zeros corresponding to transitions that should be skipped.
597 13456 : itpk_min = MINVAL(Bsp%vcks2t(:,:,ikp_bz,spin2), MASK=(Bsp%vcks2t(:,:,ikp_bz,spin2)>0) )
598 13456 : itpk_max = MAXVAL(Bsp%vcks2t(:,:,ikp_bz,spin2))
599 1088 : if (my_cols(2)<itpk_min .or. my_cols(1)>itpk_max) CYCLE
600 :
601 836 : write(msg,'(3(a,i0))')" status: ",ikp_bz,"/",BSp%nkbz," done by node ",my_rank
602 836 : call wrtout(std_out, msg, do_flush=.True.)
603 :
604 : ! * Get ikp_ibz, non-symmorphic phase, ph_mkpt, and symmetries from ikp_bz.
605 836 : call kmesh%get_BZ_item(ikp_bz,kpbz,ikp_ibz,isym_kp,itim_kp,ph_mkpt,isirred=isirred)
606 : !ABI_CHECK(isirred,"not irred!")
607 : !ABI_CHECK(ph_mkpt == cone, "Wrong phase!")
608 :
609 6059836 : ktabr_kp(:) = ktabr(:,ikp_bz)
610 4180 : spinrot_kp(:)=Cryst%spinrot(:,isym_kp)
611 : !ABI_CHECK(ALL(ktabr_kp == id_tab), "wrong tab")
612 :
613 23600 : do ik_bz=1,ikp_bz ! Loop over k
614 : !
615 : ! * Get ik_ibz, non-symmorphic phase, ph_mkt, and symmetries from ik_bz
616 22740 : call kmesh%get_BZ_item(ik_bz,kbz,ik_ibz,isym_k,itim_k,ph_mkt,isirred=isirred)
617 : !ABI_CHECK(isirred,"not irred!")
618 : !ABI_CHECK(ph_mkt == cone, "Wrong phase!")
619 :
620 172008240 : ktabr_k(:) = ktabr(:,ik_bz)
621 113700 : spinrot_k(:)=Cryst%spinrot(:,isym_k)
622 : !ABI_CHECK(ALL(ktabr_k == id_tab), "wrong tab")
623 : !if(itim_k==2) CYCLE ! time-reversal or not
624 : !
625 : ! * Find q = K-KP-G0 in the full BZ.
626 90960 : kmkp = Kmesh%bz(:,ik_bz) - Kmesh%bz(:,ikp_bz)
627 22740 : call findqg0(iq_bz,g0,kmkp,Qmesh%nbz,Qmesh%bz,BSp%mG0)
628 :
629 : ! Evaluate the tables needed for the padded FFT performed in rhotwg. Note that we have
630 : ! to pass G-G0 to sphereboundary instead of G as we need FFT results on the shifted G-sphere,
631 : ! If Gamma is not inside G-G0 one has to disable FFT padding as sphereboundary will give wrong tables.
632 : ! * Get the G-G0 shift for the FFT of the oscillators.
633 : !
634 90960 : ABI_MALLOC(gbound,(2*mgfft_osc+8,2))
635 22740 : call Gsph_c%fft_tabs(g0,mgfft_osc,ngfft_osc,use_padfft,gbound,igfftg0)
636 22740 : if ( ANY(fftalga_osc == (/2,4/)) ) use_padfft=0 ! Pad-FFT is not coded in rho_tw_g
637 22740 : if (use_padfft==0) then
638 28 : ABI_FREE(gbound)
639 56 : ABI_MALLOC(gbound,(2*mgfft_osc+8,2*use_padfft))
640 : end if
641 : !
642 : ! Get iq_ibz, and symmetries from iq_bz
643 22740 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
644 22740 : is_qeq0 = (normv(qbz,Cryst%gmet,'G')<GW_TOLQ0)
645 :
646 : ! Symmetrize em1(omega=0)
647 22740 : call screen%rotate_iqbz(iq_bz, Cryst, Gsph_c, Qmesh, Vcp)
648 :
649 : ! Set up table of |q_BZ+G|
650 22740 : if (iq_ibz==1) then
651 40208 : do ig=1,npweps
652 39372 : isg = Gsph_c%rottb(ig,itim_q,isym_q)
653 40208 : vc_sqrt_qbz(isg)=Vcp%vcqlwl_sqrt(ig,1)
654 : end do
655 : else
656 1014192 : do ig=1,npweps
657 992288 : isg = Gsph_c%rottb(ig,itim_q,isym_q)
658 1014192 : vc_sqrt_qbz(isg) = Vcp%vc_sqrt(ig,iq_ibz)
659 : end do
660 : end if
661 :
662 : ! === Evaluate oscillator matrix elements ===
663 : ! * $ <phj/r|e^{-i(q+G)}|phi/r> - <tphj/r|e^{-i(q+G)}|tphi/r> $ in packed form.
664 22740 : if (Wfd%usepaw==1.and.ik_bz/=ikp_bz) then
665 4108 : ABI_MALLOC(Pwij_q,(Cryst%ntypat))
666 1020 : call pawpwij_init(Pwij_q,npweps,Qmesh%bz(:,iq_bz),Gsph_c%gvec,Cryst%rprimd,Psps,Pawtab,Paw_pwff)
667 : end if
668 :
669 : ! =======================================
670 : ! === Loop over the four band indices ===
671 : ! =======================================
672 90388 : do ic=bidx(1,2),bidx(2,2) !do ic=BSp%lumo,BSp%nbnds
673 :
674 67648 : ABI_CHECK(wfd%get_wave_ptr(ic, ik_ibz, spin1, wave_ck, msg) == 0, msg)
675 67648 : if (wave_ck%has_ur == WFD_STORED) then
676 67420 : ptur_ck => wave_ck%ur
677 : else
678 228 : call wfd%get_ur(ic,ik_ibz,spin1,ur_ck)
679 228 : ptur_ck => ur_ck
680 : end if
681 : !
682 : ! Get cprj for this (c,kbz,s1) in the BZ.
683 : ! phase due to the umklapp G0 in k-q is already included.
684 67648 : if (Wfd%usepaw==1) then
685 4296 : if (wave_ck%has_cprj == WFD_STORED) then
686 4296 : ptcp_ck => wave_ck%cprj
687 : else
688 0 : call wfd%get_cprj(ic,ik_ibz,spin1,Cryst,Cp_tmp1,sorted=.FALSE.)
689 0 : ptcp_ck => Cp_tmp1
690 : end if
691 4296 : call paw_symcprj_op(ik_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_ck,Cp_ck)
692 : end if
693 :
694 306004 : do icp=bidx(1,4),bidx(2,4) !do icp=BSp%lumo,BSp%nbnds
695 : ! Calculate matrix-elements rhxtwg_cpc
696 : !
697 215616 : if (ik_bz==ikp_bz) then ! Already in memory.
698 8688 : rhxtwg_cpc(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,icp,ic,ik_ibz,spin1),Gsph_c)
699 :
700 : else
701 : ! Calculate matrix element from wfr.
702 : ! TODO: change the order of the loops.
703 :
704 206928 : ABI_CHECK(wfd%get_wave_ptr(icp, ikp_ibz, spin2, wave_ckp, msg) == 0, msg)
705 206928 : if (wave_ckp%has_ur == WFD_STORED) then
706 206724 : ptur_ckp => wave_ckp%ur
707 : else
708 204 : call wfd%get_ur(icp,ikp_ibz,spin2,ur_ckp)
709 204 : ptur_ckp => ur_ckp
710 : end if
711 :
712 : ! Load cprj for this (c,k,s2) in the BZ.
713 : ! Do not care about umklapp G0 in k-q as the phase is already included.
714 206928 : if (Wfd%usepaw==1) then
715 15984 : if (wave_ckp%has_cprj == WFD_STORED) then
716 15984 : ptcp_ckp => wave_ckp%cprj
717 : else
718 0 : call wfd%get_cprj(icp,ikp_ibz,spin2,Cryst,Cp_tmp2,sorted=.FALSE.)
719 0 : ptcp_ckp => Cp_tmp2
720 : end if
721 15984 : call paw_symcprj_op(ikp_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_ckp,Cp_ckp)
722 : end if
723 :
724 : call rho_tw_g(nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere,use_padfft,igfftg0,gbound,&
725 : ptur_ckp,itim_kp,ktabr_kp,ph_mkpt,spinrot_kp,&
726 : ptur_ck ,itim_k ,ktabr_k ,ph_mkt ,spinrot_k ,&
727 206928 : dim_rtwg,rhxtwg_cpc)
728 :
729 206928 : if (Wfd%usepaw==1) then ! Add PAW onsite contribution.
730 15984 : call paw_rho_tw_g(cryst,Pwij_q,npweps,dim_rtwg,nspinor,Gsph_c%gvec, Cp_ckp,Cp_ck,rhxtwg_cpc)
731 : end if
732 : end if
733 :
734 215616 : if (BSp%prep_interp) then
735 30528 : aa_cpc = rhxtwg_cpc
736 29376 : aa_cpc(2:) = czero
737 30528 : bb_cpc1 = vc_sqrt_qbz*rhxtwg_cpc
738 576 : bb_cpc1(1) = czero
739 30528 : bb_cpc2 = rhxtwg_cpc
740 29376 : bb_cpc2(2:) = czero
741 :
742 576 : if(ik_bz == ikp_bz) then
743 : ! Enforce orthogonality of the wavefunctions.
744 128 : if(icp == ic) then
745 32 : aa_cpc(1) = cone
746 32 : bb_cpc2(1) = cone
747 : else
748 96 : aa_cpc(1) = czero
749 96 : bb_cpc2(1) = czero
750 : end if
751 : end if
752 :
753 : ! MG TODO: a does not require a call to w0gemv
754 576 : call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,aa_cpc,aa_ctccp)
755 576 : call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,bb_cpc1,bb_ctccp1)
756 576 : call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,bb_cpc2,bb_ctccp2)
757 :
758 30528 : cc_cpc = vc_sqrt_qbz*rhxtwg_cpc
759 576 : cc_cpc(1) = czero
760 :
761 576 : call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,cc_cpc,cc_ctccp)
762 : end if
763 :
764 : ! Prepare sum_GG' rho_c'c*(G) W_qbz(G,G') rho_v'v(G')
765 : ! First sum on G: sum_G rho_c'c(G) W_qbz*(G,G') (W_qbz conjugated)
766 9953856 : rhxtwg_cpc = rhxtwg_cpc * vc_sqrt_qbz
767 215616 : call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,rhxtwg_cpc,ctccp)
768 :
769 921936 : do iv=bidx(1,1),bidx(2,1) !do iv=BSp%lomo,BSp%homo
770 638672 : it = BSp%vcks2t(iv,ic,ik_bz,spin1); if (it==0) CYCLE ! ir-uv-cutoff
771 638672 : ene_t = BSp%Trans(it,spin1)%en
772 :
773 : ! TODO: use this but change the order of the loops.
774 638672 : ABI_CHECK(wfd%get_wave_ptr(iv, ik_ibz, spin1, wave_vk, msg) == 0, msg)
775 :
776 638672 : if (wave_vk%has_ur == WFD_STORED) then
777 638453 : ptur_vk => wave_vk%ur
778 : else
779 219 : call wfd%get_ur(iv,ik_ibz,spin1,ur_vk)
780 219 : ptur_vk => ur_vk
781 : end if
782 : !
783 : ! Load cprj for this (v,k,s1) in the BZ.
784 : ! Do not care about umklapp G0 in k-q as the phase is already included.
785 638672 : if (Wfd%usepaw==1) then
786 51264 : if (wave_vk%has_cprj == WFD_STORED) then
787 51264 : ptcp_vk => wave_vk%cprj
788 : else
789 0 : call wfd%get_cprj(iv,ik_ibz,spin1,Cryst,Cp_tmp3,sorted=.FALSE.)
790 0 : ptcp_vk => Cp_tmp3
791 : end if
792 51264 : call paw_symcprj_op(ik_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_vk,Cp_vk)
793 : end if
794 :
795 2773248 : do ivp=bidx(1,3),bidx(2,3) !do ivp=BSp%lomo,BSp%homo
796 :
797 1918960 : if (is_resonant) then
798 1842928 : itp = BSp%vcks2t(ivp,icp,ikp_bz,spin2)
799 : else ! have to exchange band indices
800 76032 : itp = BSp%vcks2t(icp,ivp,ikp_bz,spin2)
801 : end if
802 :
803 1918960 : if (itp==0) CYCLE ! ir-uv-cutoff
804 :
805 : ! FIXME Temporary work around, when ikp_bz == ik it might happen that itp<it
806 : ! should rewrite the loops using contracted k-dependent indices for bands
807 1918960 : if (itp<it) CYCLE
808 :
809 1883684 : ir = it + itp*(itp-1)/2
810 1883684 : if (ir<t_start(my_rank).or.ir>t_stop(my_rank)) CYCLE
811 :
812 1877264 : ene_tp = BSp%Trans(itp,spin2)%en
813 :
814 : ! ============================================
815 : ! === Calculate matrix elements rhxtwg_vpv ===
816 : ! ============================================
817 1877264 : if (ik_bz==ikp_bz) then
818 : ! Already in memory.
819 42928 : rhxtwg_vpv(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,ivp,iv,ik_ibz,spin1),Gsph_c)
820 :
821 : else
822 :
823 1834336 : ABI_CHECK(wfd%get_wave_ptr(ivp, ikp_ibz, spin2, wave_vkp, msg) == 0, msg)
824 :
825 : ! Calculate matrix element from wfr.
826 1834336 : if (wave_vkp%has_ur == WFD_STORED) then
827 1834123 : ptur_vkp => wave_vkp%ur
828 : else
829 213 : call wfd%get_ur(ivp,ikp_ibz,spin2,ur_vkp)
830 213 : ptur_vkp => ur_vkp
831 : end if
832 : !
833 : ! Load cprj for this (vp,kp,s2) in the BZ.
834 : ! Do not care about umklapp G0 in k-q as the phase is already included.
835 1834336 : if (Wfd%usepaw==1) then
836 144640 : if (wave_vkp%has_cprj == WFD_STORED) then
837 144640 : ptcp_vkp => wave_vkp%cprj
838 : else
839 0 : call wfd%get_cprj(ivp,ikp_ibz,spin2,Cryst,Cp_tmp4,sorted=.FALSE.)
840 0 : ptcp_vkp => Cp_tmp4
841 : end if
842 144640 : call paw_symcprj_op(ikp_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_vkp,Cp_vkp)
843 : end if
844 :
845 : call rho_tw_g(nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere,use_padfft,igfftg0,gbound,&
846 : ptur_vkp,itim_kp,ktabr_kp,ph_mkpt,spinrot_kp,&
847 : ptur_vk ,itim_k ,ktabr_k ,ph_mkt ,spinrot_k ,&
848 1834336 : dim_rtwg,rhxtwg_vpv)
849 :
850 1834336 : if (Wfd%usepaw==1) then ! Add PAW onsite contribution.
851 144640 : call paw_rho_tw_g(cryst,Pwij_q,npweps,dim_rtwg,nspinor,Gsph_c%gvec,Cp_vkp,Cp_vk,rhxtwg_vpv)
852 : end if
853 : end if
854 :
855 : ! Index in the global Hamiltonian matrix.
856 : ir = it + itp*(itp-1_i8b)/2
857 :
858 1877264 : if (ir<t_start(my_rank).or.ir>t_stop(my_rank)) then
859 0 : write(msg,'(a,3(1x,i0))')" Gonna SIGFAULT, ir, t_start, t_stop ",ir,t_start(my_rank),t_stop(my_rank)
860 0 : ABI_ERROR(msg)
861 : end if
862 : !ABI_CHECK(itp >= it,"itp < it")
863 :
864 1877264 : if (BSp%prep_interp) then
865 : ! Save a,b, c coefficients.
866 246768 : aa_vpv = rhxtwg_vpv
867 237456 : aa_vpv(2:) = czero
868 246768 : bb_vpv1 = rhxtwg_vpv
869 237456 : bb_vpv1(2:) = czero
870 246768 : bb_vpv2 = vc_sqrt_qbz*rhxtwg_vpv
871 4656 : bb_vpv2(1) = czero
872 :
873 4656 : if (ik_bz == ikp_bz) then
874 : ! Enforce orthogonality of the wavefunctions.
875 624 : if (ivp == iv) then
876 240 : aa_vpv(1) = cone
877 240 : bb_vpv1(1) = cone
878 : else
879 384 : aa_vpv(1) = czero
880 384 : bb_vpv1(1) = czero
881 : end if
882 : end if
883 :
884 246768 : cc_vpv = vc_sqrt_qbz*rhxtwg_vpv
885 4656 : cc_vpv(1) = czero
886 :
887 4656 : aatmp = -faq * xdotc(npweps,aa_ctccp,1,aa_vpv,1)
888 4656 : bbtmp = -faq * xdotc(npweps,bb_ctccp1,1,bb_vpv1,1)-faq*xdotc(npweps,bb_ctccp2,1,bb_vpv2,1)
889 4656 : cctmp = -faq * xdotc(npweps,cc_ctccp,1,cc_vpv,1)
890 :
891 4656 : acoeffs(ir) = aatmp
892 4656 : bcoeffs(ir) = bbtmp
893 4656 : ccoeffs(ir) = cctmp
894 : end if
895 :
896 : ! sum_G2 rho_c'c(G) W_qbz(G,G') rho_v'v(G')
897 87272848 : rhxtwg_vpv = vc_sqrt_qbz * rhxtwg_vpv
898 1877264 : http = - faq * xdotc(npweps,ctccp,1,rhxtwg_vpv,1)
899 :
900 : ! Save result taking into account the symmetry of the matrix.
901 : ! Note that the diagonal of the resonant block is not forced to be real
902 2557632 : my_bsham(ir) = http
903 :
904 : #ifdef DEV_MG_DEBUG_MODE
905 : ttp_check(it,itp) = ttp_check(it,itp)+1
906 : #endif
907 : end do !ivp
908 : end do !iv
909 : end do !icp
910 : end do !ic
911 :
912 22740 : ABI_FREE(gbound)
913 :
914 23828 : if (Wfd%usepaw==1.and.ik_bz/=ikp_bz) then ! Free the onsite contribution for this q.
915 1020 : call pawpwij_free(Pwij_q)
916 2068 : ABI_FREE(Pwij_q)
917 : end if
918 :
919 : end do ! ik_bz
920 : end do ! Fat loop over ikp_bz
921 :
922 : #ifdef DEV_MG_DEBUG_MODE
923 : do itp=1,BSp%nreh(block)
924 : do it=1,BSp%nreh(block)
925 : ir = it + itp*(itp-1_i8b)/2
926 : if (itp>=it .and. ttp_check(it,itp) /= 1) then
927 : if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
928 : write(std_out,*)"WARN: upper triangle is not 1 ",it,itp,ttp_check(it,itp)
929 : write(std_out,*)TRIM(repr_trans(Bsp%Trans(it ,spin1)))
930 : write(std_out,*)TRIM(repr_trans(Bsp%Trans(itp,spin2)))
931 : end if
932 : end if
933 : if (itp< it .and. ttp_check(it,itp) /= 0) then
934 : write(std_out,*)"WARN: then lower triangle is not 0 ",it,itp,ttp_check(it,itp)
935 : write(std_out,*)TRIM(repr_trans(Bsp%Trans(it ,spin1)))
936 : write(std_out,*)TRIM(repr_trans(Bsp%Trans(itp,spin2)))
937 : end if
938 : end do
939 : end do
940 : ierr = SUM(SUM(ttp_check,DIM=2),DIM=1)
941 : if (ierr/=my_hsize) then
942 : write(msg,'(a,2i0)')"ierr/=my_hsize",ierr,my_hsize
943 : ABI_ERROR(msg)
944 : end if
945 : ABI_FREE(ttp_check)
946 : #endif
947 :
948 24 : ABI_FREE(ctccp)
949 24 : if(Bsp%prep_interp) then
950 1 : ABI_FREE(aa_ctccp)
951 1 : ABI_FREE(bb_ctccp1)
952 1 : ABI_FREE(bb_ctccp2)
953 1 : ABI_FREE(cc_ctccp)
954 : end if
955 :
956 24 : ABI_FREE(vc_sqrt_qbz)
957 24 : call wrtout(std_out,' Coulomb term completed')
958 :
959 24 : call timab(682,2,tsec) ! exc_build_ham(Coulomb)
960 : end if ! do_coulomb_term
961 : !
962 : ! =====================
963 : ! === Exchange term ===
964 : ! =====================
965 : ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
966 : ! TODO might used enlarged G-sphere for better convergence.
967 24 : if (do_exchange_term) then
968 :
969 : !call exc_build_v(spin1,spin2,nsppol,npweps,Bsp,Cryst,Kmesh,Qmesh,Gsph_x,Gsph_c,Vcp,&
970 : ! & is_resonant,rhxtwg_q0,nproc,my_rank,t_start,t_stop,my_bsham,comm)
971 :
972 24 : call timab(683,1,tsec) ! exc_build_ham(exchange)
973 :
974 24 : write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
975 24 : call wrtout(std_out, msg)
976 :
977 72 : ABI_MALLOC(rhotwg1,(npweps))
978 48 : ABI_MALLOC(rhotwg2,(npweps))
979 :
980 24 : ngx = Gsph_x%ng
981 72 : ABI_MALLOC(vc_sqrt_qbz,(ngx))
982 :
983 : ! * Get iq_ibz, and symmetries from iq_bz.
984 24 : iq_bz = iqbz0 ! q = 0 -> iqbz0
985 24 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
986 :
987 : ! * Set up table of |q(BZ)+G|
988 24 : if (iq_ibz==1) then
989 7078 : do ig=1,ngx
990 7054 : ISg = Gsph_x%rottb(ig,itim_q,isym_q)
991 7078 : vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
992 : end do
993 : else
994 0 : ABI_ERROR("iq_ibz should be 1")
995 : end if
996 :
997 9272 : do itp=1,BSp%nreh(block) ! Loop over transition tp = (kp,vp,cp,spin2)
998 :
999 9248 : if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
1000 7716 : ene_tp = Bsp%Trans(itp,spin2)%en
1001 7716 : ikp_bz = Bsp%Trans(itp,spin2)%k
1002 7716 : ivp = Bsp%Trans(itp,spin2)%v
1003 7716 : icp = Bsp%Trans(itp,spin2)%c
1004 :
1005 7716 : ikp_ibz = Kmesh%tab (ikp_bz)
1006 7716 : isym_kp = Kmesh%tabo(ikp_bz)
1007 7716 : itim_kp = (3-Kmesh%tabi(ikp_bz))/2
1008 :
1009 7716 : if (is_resonant) then
1010 7332 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
1011 : else ! Code for coupling block.
1012 384 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
1013 : end if
1014 : !
1015 : ! Multiply by the Coulomb term.
1016 365516 : do ig=2,npweps
1017 365516 : rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
1018 : end do
1019 :
1020 1886073 : do it=1,itp ! Loop over transition t = (k,v,c,spin1)
1021 1878333 : ir = it + itp*(itp-1_i8b)/2
1022 1878333 : if (ir<t_start(my_rank) .or. ir>t_stop(my_rank)) CYCLE
1023 :
1024 1877264 : ene_t = Bsp%Trans(it,spin1)%en
1025 1877264 : ik_bz = Bsp%Trans(it,spin1)%k
1026 1877264 : iv = Bsp%Trans(it,spin1)%v
1027 1877264 : ic = Bsp%Trans(it,spin1)%c
1028 :
1029 1877264 : ik_ibz = Kmesh%tab(ik_bz)
1030 1877264 : isym_k = Kmesh%tabo(ik_bz)
1031 1877264 : itim_k = (3-Kmesh%tabi(ik_bz))/2
1032 : !if (itim_k==2) CYCLE ! time-reversal or not
1033 :
1034 1877264 : rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
1035 : !
1036 : ! sum over G/=0
1037 1877264 : ctemp = xdotc(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
1038 1877264 : ctemp = faq * kx_fact * ctemp
1039 :
1040 : ! exchange term is non divergent !
1041 1877264 : if (BSp%prep_interp) then
1042 4656 : ccoeffs(ir) = ccoeffs(ir) + ctemp
1043 : end if
1044 :
1045 1887581 : my_bsham(ir) = my_bsham(ir) + ctemp
1046 : end do !it
1047 : end do !itp
1048 :
1049 24 : ABI_FREE(rhotwg1)
1050 24 : ABI_FREE(rhotwg2)
1051 24 : ABI_FREE(vc_sqrt_qbz)
1052 :
1053 24 : call timab(683,2,tsec) ! exc_build_ham(exchange)
1054 : end if ! do_exchange_term
1055 : !
1056 : ! =====================
1057 : ! === Diagonal term ===
1058 : ! =====================
1059 24 : if (is_resonant .and. spin1==spin2) then
1060 23 : write(msg,'(a,2i2,a)')" Adding diagonal term for (spin1,spin2) ",spin1,spin2," ..."
1061 23 : call wrtout(std_out, msg)
1062 8887 : do it=1,BSp%nreh(block)
1063 8864 : ir = it + it*(it-1_i8b)/2
1064 8887 : if (ir>=t_start(my_rank) .and. ir<=t_stop(my_rank)) my_bsham(ir) = my_bsham(ir) + Bsp%Trans(it,spin1)%en
1065 : end do
1066 : end if
1067 :
1068 : if (.FALSE.) then
1069 : dump_unt = get_unit()
1070 : msg=' Coupling Hamiltonian matrix elements: '
1071 : if (is_resonant) msg=' Reasonant Hamiltonian matrix elements: '
1072 : call wrtout(dump_unt, msg)
1073 : call wrtout(dump_unt,' k v c s k" v" c" s" H')
1074 : do itp=1,BSp%nreh(block)
1075 : ikp_bz = Bsp%Trans(itp,spin2)%k
1076 : ivp = Bsp%Trans(itp,spin2)%v
1077 : icp = Bsp%Trans(itp,spin2)%c
1078 : do it=1,itp
1079 : ik_bz = Bsp%Trans(it,spin1)%k
1080 : iv = Bsp%Trans(it,spin1)%v
1081 : ic = Bsp%Trans(it,spin1)%c
1082 : ir = it + itp*(itp-1_i8b)/2
1083 : if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
1084 : http = my_bsham(ir)
1085 : !if (ABS(http) > tol3) then
1086 : write(msg,'(2(i0,1x),2(i5,3i3,3x),2f7.3)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,spin2, http
1087 : call wrtout(dump_unt, msg)
1088 : !end if
1089 : end if
1090 : end do
1091 : end do
1092 : end if
1093 :
1094 : !DBYG
1095 : if (.False.) then
1096 : dump_unt = get_unit()
1097 : dump_unt = 999
1098 : msg=' Coupling Hamiltonian matrix elements: '
1099 : if (is_resonant) msg=' Resonant Hamiltonian matrix elements: '
1100 : call wrtout(dump_unt, msg)
1101 : call wrtout(dump_unt,' k v c s k" v" c" s" H')
1102 : do itp=1,BSp%nreh(block)
1103 : ikp_bz = Bsp%Trans(itp,spin2)%k
1104 : ivp = Bsp%Trans(itp,spin2)%v
1105 : icp = Bsp%Trans(itp,spin2)%c
1106 : do it=1,BSp%nreh(block)
1107 : ik_bz = Bsp%Trans(it,spin1)%k
1108 : iv = Bsp%Trans(it,spin1)%v
1109 : ic = Bsp%Trans(it,spin1)%c
1110 : if(it > itp) then
1111 : ir = itp+it*(it-1_i8b)/2
1112 : else
1113 : ir = it + itp*(itp-1_i8b)/2
1114 : end if
1115 : if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
1116 : if(it > itp) then
1117 : http = CONJG(my_bsham(ir))
1118 : if (BSp%prep_interp) then
1119 : aatmp = CONJG(acoeffs(ir))
1120 : bbtmp = CONJG(bcoeffs(ir))
1121 : cctmp = CONJG(ccoeffs(ir))
1122 : end if
1123 : else
1124 : http = my_bsham(ir)
1125 : if (BSp%prep_interp) then
1126 : aatmp = acoeffs(ir)
1127 : bbtmp = bcoeffs(ir)
1128 : cctmp = ccoeffs(ir)
1129 : end if
1130 : end if
1131 : if (it == itp) http = http - Bsp%Trans(it,spin1)%en
1132 : !if (ABS(http) > tol3) then
1133 : if (BSp%prep_interp) then
1134 : write(msg,'(2(i0,1x),2(i5,3i3,3x),2f24.20,2f24.20,2f24.20,2f24.20)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,&
1135 : & spin2, http, aatmp, bbtmp, cctmp
1136 : else
1137 : write(msg,'(2(i0,1x),2(i5,3i3,3x),2f24.20)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,spin2, http
1138 : end if
1139 : call wrtout(dump_unt, msg)
1140 : !end if
1141 : end if
1142 : end do
1143 : end do
1144 : end if
1145 :
1146 24 : call timab(684,1,tsec) ! exc_build_ham(synchro)
1147 24 : call xmpi_barrier(comm)
1148 24 : call timab(684,2,tsec) ! exc_build_ham(synchro)
1149 : !
1150 : ! =================================
1151 : ! === Write Hamiltonian on disk ===
1152 : ! =================================
1153 24 : call timab(685,1,tsec) ! exc_build_ham(write_ham)
1154 48 : if (use_mpiio) then
1155 : #ifdef HAVE_MPI_IO
1156 : ! Write the Hamiltonian with collective MPI-IO.
1157 : if (BSp%prep_interp) then
1158 : ABI_ERROR("Preparation of interpolation technique not yet coded with MPI-IO")
1159 : end if
1160 : ABI_CHECK(nsppol==1,"nsppol==2 not coded, offset is wrong")
1161 : !
1162 : old_type = MPI_DOUBLE_COMPLEX
1163 : call xmpio_create_fherm_packed(my_starts,my_ends,is_fortran_file,my_offset,old_type,hmat_type,offset_err)
1164 :
1165 : if (offset_err/=0) then
1166 : write(msg,"(3a)")&
1167 : "Global position index cannot be stored in a standard Fortran integer. ",ch10,&
1168 : "BSE matrix cannot be written with a single MPI-IO call. "
1169 : ABI_ERROR(msg)
1170 : end if
1171 : !
1172 : ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
1173 : my_offset = offset_of_block(block) + my_offset
1174 :
1175 : call MPI_FILE_SET_VIEW(mpi_fh, my_offset, MPI_BYTE, hmat_type, 'native', MPI_INFO_NULL, mpi_err)
1176 : ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1177 :
1178 : call MPI_TYPE_FREE(hmat_type,mpi_err)
1179 : ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1180 :
1181 : if (hsize_of(my_rank) /= INT(hsize_of(my_rank),kind=i4b) ) then
1182 : ABI_ERROR("Wraparound error")
1183 : end if
1184 :
1185 : tmp_size = INT(hsize_of(my_rank))
1186 : call MPI_FILE_WRITE_ALL(mpi_fh, my_bsham, tmp_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1187 : ABI_CHECK_MPI(mpi_err,"FILE_WRITE")
1188 :
1189 : ! It seems that personal calls in make the code stuck
1190 : !if (is_fortran_file .and. my_rank==master) then ! Master writes the Fortran record markers.
1191 : ! Write the Fortran record markers.
1192 : neh2=BSp%nreh(block)
1193 : ABI_MALLOC(bsize_frecord,(neh2))
1194 : bsize_frecord = (/(col_glob * xmpi_bsize_dpc, col_glob=1,neh2)/)
1195 : ! ehdr_offset points to the end of the header.
1196 : !call xmpio_write_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,neh2,bsize_frecord,mpi_err)
1197 : my_offset = offset_of_block(block)
1198 : call xmpio_write_frmarkers(mpi_fh,my_offset,xmpio_collective,neh2,bsize_frecord,ierr)
1199 : ABI_CHECK(ierr==0,"Error while writing Fortran markers")
1200 : ABI_FREE(bsize_frecord)
1201 : #else
1202 : ABI_BUG("You should not be here!")
1203 : #endif
1204 : else
1205 : ! Use FORTRAN IO with sequential access mode.
1206 : ! * Each node sends its data to master node.
1207 : ! * Blocks are distributed according to the rank of the node.
1208 : ! * Matrix is written by columns hence make sure that the last column is completely written.
1209 24 : call cwtime(cputime,walltime,gflops,"start")
1210 :
1211 24 : if (my_rank==master) then
1212 20 : prev_nrows=0; if (my_cols(2) /= my_rows(2)) prev_nrows = my_rows(2)
1213 20 : ncol = my_cols(2)-my_cols(1)+1
1214 20 : ist=1
1215 7428 : do jj=1,ncol
1216 7408 : col_glob = my_starts(2) + jj - 1
1217 7408 : nrows = col_glob; if (jj==ncol) nrows=my_rows(2)
1218 7408 : iend = ist + nrows -1
1219 7408 : write(bsh_unt) my_bsham(ist:iend)
1220 7408 : if (BSp%prep_interp) then
1221 96 : write(a_unt) acoeffs(ist:iend)
1222 96 : write(b_unt) bcoeffs(ist:iend)
1223 96 : write(c_unt) ccoeffs(ist:iend)
1224 : end if
1225 7428 : ist=iend+1
1226 : end do
1227 20 : write(msg,'(2(a,i0))')" Wraparound error: iend=",iend," my_hsize=",hsize_of(my_rank)
1228 20 : ABI_CHECK(iend == hsize_of(my_rank),msg)
1229 20 : ABI_FREE(my_bsham)
1230 20 : if (BSp%prep_interp) then
1231 1 : ABI_FREE(acoeffs)
1232 1 : ABI_FREE(bcoeffs)
1233 1 : ABI_FREE(ccoeffs)
1234 : end if
1235 : end if
1236 :
1237 24 : call xmpi_barrier(comm)
1238 : !
1239 : ! Collect data from the other nodes.
1240 38 : do sender=1,nproc-1
1241 : ! If I'm not involved, jump to the end of the loop and wait there (sequential IO? Of course!)
1242 14 : if (all(my_rank /= [sender, master])) goto 100
1243 :
1244 8 : if (my_rank==master) then
1245 12 : ABI_MALLOC(buffer,(hsize_of(sender)))
1246 4 : if (BSp%prep_interp) then
1247 0 : ABI_MALLOC(abuffer,(hsize_of(sender)))
1248 0 : ABI_MALLOC(bbuffer,(hsize_of(sender)))
1249 0 : ABI_MALLOC(cbuffer,(hsize_of(sender)))
1250 : end if
1251 : end if
1252 8 : tmp_size = INT(hsize_of(sender),kind=i4b)
1253 8 : call xmpi_exch(my_bsham,tmp_size,sender,buffer,master,comm,10*block+1,mpi_err)
1254 8 : if (BSp%prep_interp) then
1255 0 : call xmpi_exch(acoeffs,tmp_size,sender,abuffer,master,comm,10*block+2,mpi_err)
1256 0 : call xmpi_exch(bcoeffs,tmp_size,sender,bbuffer,master,comm,10*block+3,mpi_err)
1257 0 : call xmpi_exch(ccoeffs,tmp_size,sender,cbuffer,master,comm,10*block+4,mpi_err)
1258 : end if
1259 :
1260 : ! TODO Be careful with the MPI TAG here, add optional Arguments in xmpi_exch so that the TAG can be specified!
1261 24 : proc_start = (/my_rows(1),my_cols(1)/)
1262 24 : proc_end = (/my_rows(2),my_cols(2)/)
1263 24 : my_extrema(:,1) = proc_start
1264 24 : my_extrema(:,2) = proc_end
1265 :
1266 8 : sender_extrema = my_extrema ! just to avoid NAN on sender. xechh_mpi is not well designed
1267 8 : call xmpi_exch(my_extrema,4,sender,sender_extrema,master,comm,10*block+5,mpi_err)
1268 :
1269 8 : if (my_rank==master) then
1270 12 : proc_start = sender_extrema(:,1)
1271 12 : proc_end = sender_extrema(:,2)
1272 : !write(std_out,*)"proc_start, proc_end",proc_start,proc_end
1273 :
1274 4 : if (prev_nrows>0) then ! backspace the file if the last record written was not complete.
1275 : !write(std_out,*)" master node had to call backspace"
1276 4 : backspace(bsh_unt)
1277 12 : ABI_MALLOC(prev_col,(prev_nrows))
1278 4 : read(bsh_unt) prev_col
1279 4 : backspace(bsh_unt)
1280 :
1281 4 : if (BSp%prep_interp) then
1282 0 : backspace(a_unt)
1283 0 : ABI_MALLOC(aprev_col,(prev_nrows))
1284 0 : read(a_unt) aprev_col
1285 0 : backspace(a_unt)
1286 :
1287 0 : backspace(b_unt)
1288 0 : ABI_MALLOC(bprev_col,(prev_nrows))
1289 0 : read(b_unt) bprev_col
1290 0 : backspace(b_unt)
1291 :
1292 0 : backspace(c_unt)
1293 0 : ABI_MALLOC(cprev_col,(prev_nrows))
1294 0 : read(c_unt) cprev_col
1295 0 : backspace(c_unt)
1296 : end if
1297 : end if
1298 : !
1299 : ! Write the columns owned by sender.
1300 4 : ncol = proc_end(2)-proc_start(2)+1
1301 4 : ist=1
1302 312 : do jj=1,ncol
1303 308 : col_glob = proc_start(2) + jj-1
1304 308 : nrows = col_glob
1305 308 : if (jj==1 ) nrows=col_glob - proc_start(1) + 1
1306 308 : if (jj==ncol) then
1307 4 : nrows=proc_end(1)
1308 4 : if (ncol==1) nrows=proc_end(1) - proc_start(1) + 1
1309 : end if
1310 308 : iend = ist + nrows -1
1311 : !write(std_out,*)"Using nrows, ist, iend=",nrows,ist,iend
1312 308 : if (jj==1 .and. prev_nrows>0) then ! join prev_col and this subcolumn.
1313 1073 : write(bsh_unt) CMPLX(prev_col,kind=dp),CMPLX(buffer(ist:iend),kind=dp)
1314 4 : if (BSp%prep_interp) then
1315 0 : write(a_unt) CMPLX(aprev_col,kind=dp),CMPLX(abuffer(ist:iend),kind=dp)
1316 0 : write(b_unt) CMPLX(bprev_col,kind=dp),CMPLX(bbuffer(ist:iend),kind=dp)
1317 0 : write(c_unt) CMPLX(cprev_col,kind=dp),CMPLX(cbuffer(ist:iend),kind=dp)
1318 : end if
1319 4 : prev_nrows = prev_nrows + iend-ist+1
1320 : else
1321 92149 : write(bsh_unt) CMPLX(buffer(ist:iend),kind=dp)
1322 304 : if (BSp%prep_interp) then
1323 0 : write(a_unt) CMPLX(abuffer(ist:iend),kind=dp)
1324 0 : write(b_unt) CMPLX(bbuffer(ist:iend),kind=dp)
1325 0 : write(c_unt) CMPLX(cbuffer(ist:iend),kind=dp)
1326 : end if
1327 : prev_nrows=0
1328 : end if
1329 312 : ist=iend+1
1330 : end do
1331 4 : if (ncol>1) then ! Reset prev_nrows if a new column has begun.
1332 4 : prev_nrows = proc_end(1)
1333 4 : if (proc_end(1) == proc_end(2)) prev_nrows = 0
1334 : end if
1335 4 : if (iend/=hsize_of(sender)) then
1336 0 : write(msg,'(2(a,i0))')" Wraparound error: iend=",iend," my_hsize=",hsize_of(sender)
1337 0 : ABI_ERROR(msg)
1338 : end if
1339 4 : ABI_SFREE(prev_col)
1340 4 : if (BSp%prep_interp) then
1341 0 : ABI_SFREE(aprev_col)
1342 0 : ABI_SFREE(bprev_col)
1343 0 : ABI_SFREE(cprev_col)
1344 : end if
1345 4 : ABI_FREE(buffer)
1346 4 : if (BSp%prep_interp) then
1347 0 : ABI_FREE(abuffer)
1348 0 : ABI_FREE(bbuffer)
1349 0 : ABI_FREE(cbuffer)
1350 : end if
1351 : end if ! master
1352 : !
1353 38 : 100 call xmpi_barrier(comm)
1354 : end do ! sender
1355 :
1356 24 : call cwtime(cputime,walltime,gflops,"stop")
1357 24 : write(msg,'(2(a,f9.1),a)')" Fortran-IO completed. cpu_time: ",cputime,"[s], walltime: ",walltime," [s]"
1358 24 : call wrtout(std_out, msg, do_flush=.True.)
1359 : end if ! use_mpiio
1360 24 : call timab(685,2,tsec) ! exc_build_ham(write_ham)
1361 : !
1362 24 : ABI_SFREE(my_bsham)
1363 24 : if (BSp%prep_interp) then
1364 1 : ABI_SFREE(acoeffs)
1365 1 : ABI_SFREE(bcoeffs)
1366 1 : ABI_SFREE(ccoeffs)
1367 : end if
1368 24 : ABI_FREE(t_start)
1369 24 : ABI_FREE(t_stop)
1370 47 : ABI_FREE(hsize_of)
1371 : end do ! block
1372 : !
1373 : ! ===========================================
1374 : ! === Exchange term for spin_up spin_down ===
1375 : ! ===========================================
1376 :
1377 23 : if (nsppol==2) then
1378 1 : call timab(686,2,tsec) ! exc_build_ham(exch.spin)
1379 1 : block=3
1380 1 : neh1=BSp%nreh(1)
1381 1 : neh2=BSp%nreh(2)
1382 : !
1383 : ! The oscillators at q=0 are available on each node for both spin.
1384 : ! Here the calculation of the block is parallelized over columns.
1385 3 : ABI_MALLOC(col_start,(0:nproc-1))
1386 2 : ABI_MALLOC(col_stop,(0:nproc-1))
1387 1 : call xmpi_split_work2_i4b(neh2,nproc,col_start,col_stop)
1388 :
1389 1 : my_cols(1) = col_start(my_rank)
1390 1 : my_cols(2) = col_stop (my_rank)
1391 1 : if (my_cols(2)-my_cols(1)<=0) then
1392 0 : ABI_ERROR("One of the processors has zero columns!")
1393 : end if
1394 :
1395 2 : ABI_MALLOC(ncols_of,(0:nproc-1))
1396 2 : ncols_of=0
1397 2 : do rank=0,nproc-1
1398 2 : if (col_stop(rank)>=col_start(rank)) ncols_of(rank) = col_stop(rank)-col_start(rank)+1
1399 : end do
1400 :
1401 1 : ABI_FREE(col_start)
1402 1 : ABI_FREE(col_stop)
1403 : !
1404 : ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
1405 : ! TODO might used enlarged G-sphere for better convergence.
1406 : ! Note that my_kxssp is always written on file when nsppol=2, even when
1407 : ! non-local field effects are neglected.
1408 4 : ABI_MALLOC(my_kxssp,(neh1,my_cols(1):my_cols(2)))
1409 147841 : my_kxssp=czero
1410 :
1411 1 : if (do_exchange_term) then
1412 1 : spin1=1; spin2=2
1413 1 : write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
1414 1 : call wrtout(std_out, msg)
1415 :
1416 3 : ABI_MALLOC(rhotwg1,(npweps))
1417 2 : ABI_MALLOC(rhotwg2,(npweps))
1418 :
1419 1 : ngx = Gsph_x%ng
1420 3 : ABI_MALLOC(vc_sqrt_qbz,(ngx))
1421 : !
1422 : ! * Get iq_ibz, and symmetries from iq_bz.
1423 1 : iq_bz = iqbz0 ! q = 0 -> iqbz0
1424 1 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
1425 : !
1426 : ! * Set up table of |q(BZ)+G|
1427 1 : if (iq_ibz==1) then
1428 170 : do ig=1,ngx
1429 169 : ISg = Gsph_x%rottb(ig,itim_q,isym_q)
1430 170 : vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
1431 : end do
1432 : else
1433 0 : ABI_ERROR("iq_ibz should be 1")
1434 : end if
1435 :
1436 385 : do itp=1,neh2 ! Loop over transition tp = (kp,vp,cp,spin2)
1437 :
1438 384 : if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
1439 384 : ene_tp = Bsp%Trans(itp,spin2)%en
1440 384 : ikp_bz = Bsp%Trans(itp,spin2)%k
1441 384 : ivp = Bsp%Trans(itp,spin2)%v
1442 384 : icp = Bsp%Trans(itp,spin2)%c
1443 :
1444 384 : ikp_ibz = Kmesh%tab (ikp_bz)
1445 384 : isym_kp = Kmesh%tabo(ikp_bz)
1446 384 : itim_kp = (3-Kmesh%tabi(ikp_bz))/2
1447 :
1448 384 : if (is_resonant) then
1449 384 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
1450 : else ! Code for coupling block.
1451 0 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
1452 : end if
1453 : !
1454 : ! Multiply by the Coulomb term.
1455 19584 : do ig=2,npweps
1456 19584 : rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
1457 : end do
1458 :
1459 147841 : do it=1,neh1 ! Loop over transition t = (k,v,c,spin1) FULL matrix.
1460 :
1461 147456 : ene_t = Bsp%Trans(it,spin1)%en
1462 147456 : ik_bz = Bsp%Trans(it,spin1)%k
1463 147456 : iv = Bsp%Trans(it,spin1)%v
1464 147456 : ic = Bsp%Trans(it,spin1)%c
1465 :
1466 147456 : ik_ibz = Kmesh%tab(ik_bz)
1467 147456 : isym_k = Kmesh%tabo(ik_bz)
1468 147456 : itim_k = (3-Kmesh%tabi(ik_bz))/2
1469 : !if (itim_k==2) CYCLE ! time-reversal or not
1470 :
1471 147456 : rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
1472 : !
1473 : ! sum over G/=0
1474 147456 : ctemp = XDOTC(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
1475 147456 : ctemp = faq * kx_fact * ctemp
1476 :
1477 147840 : my_kxssp(it,itp) = ctemp
1478 : end do !it
1479 : end do !itp
1480 :
1481 1 : ABI_FREE(rhotwg1)
1482 1 : ABI_FREE(rhotwg2)
1483 1 : ABI_FREE(vc_sqrt_qbz)
1484 : end if ! do_exchange_term
1485 1 : call timab(686,2,tsec) ! exc_build_ham(exch.spin)
1486 : !
1487 : ! =====================================
1488 : ! === Write the Hamiltonian on disk ===
1489 : ! =====================================
1490 1 : call timab(685,1,tsec) ! exc_build_ham(write_ham)
1491 :
1492 : if (use_mpiio) then
1493 : #ifdef HAVE_MPI_IO
1494 : my_ncols=ncols_of(my_rank); old_type=MPI_DOUBLE_COMPLEX
1495 : call xmpio_create_fsubarray_2D((/neh1,my_ncols/),(/neh1,my_ncols/),(/1,1/),old_type,hmat_type,my_offpad,mpi_err)
1496 : ABI_CHECK_MPI(mpi_err,"fsubarray_2D")
1497 : !
1498 : ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
1499 : prev_nels=0
1500 : prev_ncols=0
1501 : if (my_rank>0) then
1502 : prev_ncols = SUM(ncols_of(0:my_rank-1))
1503 : prev_nels = neh1*prev_ncols
1504 : end if
1505 : tmp_off = prev_nels*xmpi_bsize_dpc + prev_ncols*2*xmpio_bsize_frm
1506 :
1507 : my_offset = offset_of_block(block) + tmp_off + my_offpad
1508 :
1509 : call MPI_FILE_SET_VIEW(mpi_fh, my_offset, MPI_BYTE, hmat_type, 'native', MPI_INFO_NULL, mpi_err)
1510 : ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1511 :
1512 : call MPI_TYPE_FREE(hmat_type,mpi_err)
1513 : ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1514 :
1515 : tmp_size = INT(neh1*my_ncols)
1516 : call MPI_FILE_WRITE_ALL(mpi_fh, my_kxssp,tmp_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1517 : ABI_CHECK_MPI(mpi_err,"FILE_WRITE")
1518 :
1519 : ! It seems that personal calls in make the code stuck
1520 : ! Master writes the Fortran record markers.
1521 : ABI_MALLOC(bsize_frecord,(neh2))
1522 : bsize_frecord = neh1 * xmpi_bsize_dpc
1523 : ! ehdr_offset points to the end of the header.
1524 : !call xmpio_write_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,neh2,bsize_frecord,mpi_err)
1525 : my_offset = offset_of_block(block)
1526 : call xmpio_write_frmarkers(mpi_fh,my_offset,xmpio_collective,neh2,bsize_frecord,ierr)
1527 : ABI_CHECK(ierr==0,"Error while writing Fortran markers")
1528 : ABI_FREE(bsize_frecord)
1529 : #else
1530 : ABI_BUG("You should not be here")
1531 : #endif
1532 : else
1533 : ! Use FORTRAN IO with sequential access mode.
1534 : ! * Each node sends its data to master node.
1535 : ! * Columns are distributed according to the rank of the node.
1536 1 : if (my_rank==master) then
1537 385 : do jj=my_cols(1),my_cols(2)
1538 385 : write(bsh_unt) my_kxssp(:,jj)
1539 : end do
1540 1 : ABI_FREE(my_kxssp)
1541 : end if
1542 :
1543 1 : call xmpi_barrier(comm)
1544 : !
1545 : ! Collect data from the other nodes.
1546 1 : do sender=1,nproc-1
1547 : ! If I'm not involved, jump to the end of the loop and wait there (sequential IO? Of course!)
1548 0 : if (all(my_rank /= [sender, master])) goto 200
1549 :
1550 0 : if (my_rank==master) then
1551 0 : ABI_MALLOC(buffer_2d,(neh1,ncols_of(sender)))
1552 : end if
1553 0 : call xmpi_exch(my_kxssp,neh1*ncols_of(sender),sender,buffer_2d,master,comm,5,mpi_err)
1554 : !
1555 0 : if (my_rank==master) then ! Write the columns owned by sender.
1556 0 : do jj=1,ncols_of(sender)
1557 0 : write(bsh_unt) buffer_2d(:,jj)
1558 : end do
1559 0 : ABI_FREE(buffer_2d)
1560 : end if ! master
1561 : !
1562 1 : 200 call xmpi_barrier(comm)
1563 : end do ! sender
1564 : end if
1565 1 : call timab(685,2,tsec) ! exc_build_ham(write_ham)
1566 :
1567 1 : ABI_FREE(ncols_of)
1568 1 : ABI_SFREE(my_kxssp)
1569 : end if
1570 :
1571 : ! Close the file.
1572 : if (use_mpiio) then
1573 : #ifdef HAVE_MPI_IO
1574 : call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1575 : ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1576 : ABI_FREE(offset_of_block)
1577 : #endif
1578 : end if
1579 :
1580 : ! master closes the Fortran files.
1581 23 : if (my_rank==master) then
1582 19 : close(bsh_unt)
1583 19 : if (BSp%prep_interp) then
1584 1 : close(a_unt)
1585 1 : close(b_unt)
1586 1 : close(c_unt)
1587 : end if
1588 : end if
1589 :
1590 : ! Free memory.
1591 23 : ABI_FREE(igfftg0)
1592 23 : ABI_FREE(ktabr_k)
1593 23 : ABI_FREE(id_tab)
1594 23 : ABI_FREE(ktabr_kp)
1595 23 : ABI_FREE(rhxtwg_vpv)
1596 23 : ABI_FREE(rhxtwg_cpc)
1597 23 : if (BSp%prep_interp) then
1598 1 : ABI_FREE(aa_vpv)
1599 1 : ABI_FREE(bb_vpv1)
1600 1 : ABI_FREE(bb_vpv2)
1601 1 : ABI_FREE(cc_vpv)
1602 1 : ABI_FREE(aa_cpc)
1603 1 : ABI_FREE(bb_cpc1)
1604 1 : ABI_FREE(bb_cpc2)
1605 1 : ABI_FREE(cc_cpc)
1606 : end if
1607 23 : ABI_FREE(ur_ckp)
1608 23 : ABI_FREE(ur_vkp)
1609 23 : ABI_FREE(ur_vk)
1610 23 : ABI_FREE(ur_ck)
1611 :
1612 : ! Deallocation for PAW.
1613 23 : if (Wfd%usepaw==1) then
1614 2 : call pawcprj_free(Cp_vk)
1615 6 : ABI_FREE(Cp_vk)
1616 2 : call pawcprj_free(Cp_ck)
1617 6 : ABI_FREE(Cp_ck)
1618 2 : call pawcprj_free(Cp_ckp)
1619 6 : ABI_FREE(Cp_ckp)
1620 2 : call pawcprj_free(Cp_vkp)
1621 6 : ABI_FREE(Cp_vkp)
1622 2 : call pawcprj_free(Cp_tmp1)
1623 6 : ABI_FREE(Cp_tmp1)
1624 2 : call pawcprj_free(Cp_tmp2)
1625 6 : ABI_FREE(Cp_tmp2)
1626 2 : call pawcprj_free(Cp_tmp3)
1627 6 : ABI_FREE(Cp_tmp3)
1628 2 : call pawcprj_free(Cp_tmp4)
1629 6 : ABI_FREE(Cp_tmp4)
1630 : end if
1631 :
1632 23 : call xmpi_barrier(comm)
1633 :
1634 : DBG_EXIT("COLL")
1635 :
1636 23 : call timab(680,2,tsec)
1637 :
1638 46 : end subroutine exc_build_block
1639 : !!***
1640 :
1641 : !!****f* m_exc_build/exc_build_v
1642 : !! NAME
1643 : !! exc_build_v
1644 : !!
1645 : !! FUNCTION
1646 : !! Calculate and write the excitonic Hamiltonian on an external binary file (Fortran file open
1647 : !! in random mode) for subsequent treatment in the Bethe-Salpeter code.
1648 : !!
1649 : !! INPUTS
1650 : !! BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
1651 : !! Cryst<crystal_t>=Info on the crystalline structure.
1652 : !! Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
1653 : !! Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
1654 : !! Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
1655 : !! Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
1656 : !! Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
1657 : !! rhxtwg_q0
1658 : !! is_resonant
1659 : !! comm=MPI communicator.
1660 : !!
1661 : !! OUTPUT
1662 : !!
1663 : !! NOTES
1664 : !! *) Version for K_V = K_C (q=0), thus KP_V = KP_C
1665 : !! *) No exchange limit: use DFT energies in case.
1666 : !! *) Symmetry of H(-k-k') = H*(k k') not used.
1667 : !! *) Coulomb term can be approximated as diagonal in G.
1668 : !! *) Valence bands treated from lomo on.
1669 : !! *) Symmetries of the sub-blocks are used to reduce the number of elements to calculate.
1670 : !!
1671 : !! ____________
1672 : !! |_(cv)__(vc)_|
1673 : !! H_exc = | R C |
1674 : !! | -C* -R* |
1675 : !!
1676 : !! where C is symmetric and R is Hermitian provided that the QP energies are real.
1677 : !!
1678 : !! For nsppol=1 ==> R = diag-W+2v; C = -W+2v
1679 : !! since the Hamiltonian can be diagonalized in the spin-singlet basis set thanks to
1680 : !! the fact that spin triplet does not contribute to the optical limit of epsilon.
1681 : !!
1682 : !! For nsppol=2 ==> R = diag-W+v; C = -W+v
1683 : !! Now the matrix elements depend on the spin of the transitions but only those
1684 : !! transitions in which the spin of the electron and of the hole are equal contribute
1685 : !! to the macroscopic dielectric function. Moreover only the exchange term can connect transitions of different spin.
1686 : !! When nsppol==2 the transitions are ordered using | (cv up) | (cv dwn) | (vc up) | (vc down) |
1687 : !!
1688 : !! The resonant block is given by:
1689 : !!
1690 : !! | (v'c' up) | (v'c' dwn) |
1691 : !! ----------------------------------- where v_{-+} = v_{+-}^H when the momentum of the photon is neglected.
1692 : !! | [diag-W+v]++ | v+- | (vc up) Note that v_{+-} is not Hermitian due to the presence of different spins.
1693 : !! R = ----------------------------------- Actually it reduces to a Hermitian matrix when the system is not spin polarized.
1694 : !! | v-+ | [diag-W+v]-- | (vc dwn) but in this case one should use nsppol=1.
1695 : !! ----------------------------------- As a consequence the entire matrix is calculated and stored on file.
1696 : !!
1697 : !! The coupling block is given by:
1698 : !!
1699 : !! | (c'v' up) | (c'v dwn) |
1700 : !! ----------------------------------- where v_{-+} = v_{+-}^t when the momentum of the photon is neglected.
1701 : !! | [-W+v]++ | v+- | (vc up) Also in this case the entire matrix v_{+-} has to be calculated
1702 : !! C = ----------------------------------- and stored on file.
1703 : !! | v-+ | [-W+v]-- | (vc dwn)
1704 : !! -----------------------------------
1705 : !!
1706 : !! SOURCE
1707 :
1708 : subroutine exc_build_v(spin1,spin2,nsppol,npweps,Bsp,Cryst,Kmesh,Qmesh,Gsph_x,Gsph_c,Vcp,&
1709 : & is_resonant,rhxtwg_q0,nproc,my_rank,t_start,t_stop,my_bsham)
1710 :
1711 : !Arguments ------------------------------------
1712 : !scalars
1713 : integer,intent(in) :: spin1,spin2,nsppol,npweps,nproc,my_rank
1714 : logical,intent(in) :: is_resonant
1715 : type(excparam),intent(in) :: BSp
1716 : type(kmesh_t),intent(in) :: Kmesh,Qmesh
1717 : type(crystal_t),intent(in) :: Cryst
1718 : type(vcoul_t),intent(in) :: Vcp
1719 : type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
1720 : !arrays
1721 : integer(i8b),intent(in) :: t_start(0:nproc-1),t_stop(0:nproc-1)
1722 : complex(gwp),intent(in) :: rhxtwg_q0(npweps,BSp%lomo_min:BSp%humo_max,BSp%lomo_min:BSp%humo_max,Kmesh%nibz,nsppol)
1723 : complex(dp),intent(inout) :: my_bsham(t_start(my_rank):t_stop(my_rank))
1724 :
1725 : !Local variables ------------------------------
1726 : !scalars
1727 : integer :: ISg,ngx,ik_bz,ikp_bz,dim_rtwg
1728 : integer :: neh1,neh2,ig,nblocks
1729 : integer :: ik_ibz,itim_k,ikp_ibz,itim_kp,isym_k,isym_kp
1730 : integer :: iq_bz,iq_ibz,isym_q,itim_q,iqbz0,rank
1731 : integer :: iv,ivp,ic,icp
1732 : integer :: block
1733 : integer(i8b) :: tot_nels,ir,it,itp
1734 : real(dp) :: faq,kx_fact
1735 : complex(sp) :: ctemp
1736 : character(len=500) :: msg
1737 : !arrays
1738 : integer :: bidx(2,4),spin_ids(2,3), my_cols(2),my_rows(2) !,proc_end(2),proc_start(2)
1739 : integer(i8b) :: nels_block(3)
1740 : integer,allocatable :: ncols_of(:), col_start(:),col_stop(:)
1741 : real(dp) :: qbz(3),tsec(2) !kbz(3),kpbz(3),
1742 : complex(dp),allocatable :: my_kxssp(:,:)
1743 : complex(gwp),allocatable :: vc_sqrt_qbz(:),rhotwg1(:),rhotwg2(:)
1744 : !************************************************************************
1745 :
1746 : DBG_ENTER("COLL")
1747 :
1748 : write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
1749 : call wrtout(std_out, msg)
1750 :
1751 : ! Basic constants.
1752 : dim_rtwg=1; faq = one/(Cryst%ucvol*Kmesh%nbz)
1753 :
1754 : ! Identify the index of q==0
1755 : iqbz0=0
1756 : do iq_bz=1,Qmesh%nbz
1757 : if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
1758 : end do
1759 : ABI_CHECK(iqbz0/=0,"q=0 not found")
1760 : !
1761 : ! Treat the spin polarization.
1762 : spin_ids(:,1) = (/1,1/)
1763 : spin_ids(:,2) = (/2,2/)
1764 : spin_ids(:,3) = (/1,2/)
1765 :
1766 : nblocks=1
1767 : kx_fact=two
1768 : nels_block(:)=0
1769 : nels_block(1)=BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2
1770 : tot_nels=nels_block(1)
1771 :
1772 : if (nsppol==2) then
1773 : nblocks=3
1774 : kx_fact=one
1775 : nels_block(1) = BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2 ! Only the upper triangle for block 1 and 2
1776 : nels_block(2) = BSp%nreh(2)*(BSp%nreh(2)+1_i8b)/2
1777 : nels_block(3) = BSp%nreh(1)*BSp%nreh(2)*1_i8b ! Note: Block 3 does not have symmetries.
1778 : tot_nels= SUM(nels_block)
1779 : end if
1780 : !
1781 : ! Distribute the calculation of the matrix elements among the nodes.
1782 : ! * tstart and t_stop give the initial and final transition index treated by each node.
1783 : ! * my_hsize is the number of transitions treated by this processor
1784 : ! * my_cols(1:2) gives the initial and final column treated by this node.
1785 : !
1786 : do block=1,nsppol
1787 : !
1788 : ! Indices used to loop over bands.
1789 : ! bidx contains the starting and final indices used to loop over bands.
1790 : !
1791 : ! (b3,b4)
1792 : ! |... ...|
1793 : ! (b1,b2) |... ...|
1794 : !
1795 : ! Resonant matrix is given by
1796 : ! (v',c')
1797 : ! |... ...|
1798 : ! (v,c) |... ...|
1799 : !
1800 : ! Coupling matrix is given by
1801 : ! (c',v')
1802 : ! |... ...|
1803 : ! (v,c) |... ...|
1804 :
1805 : if (is_resonant) then
1806 : bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
1807 : bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
1808 : bidx(:,3) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b3
1809 : bidx(:,4) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b4
1810 : else
1811 : bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
1812 : bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
1813 : bidx(:,3) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b3
1814 : bidx(:,4) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b4
1815 : end if
1816 :
1817 : !spin1 = spin_ids(1,block)
1818 : !spin2 = spin_ids(2,block)
1819 :
1820 : my_cols=0
1821 : do itp=1,Bsp%nreh(block)
1822 : do it=1,itp
1823 : ir = it + itp*(itp-1_i8b)/2
1824 : if (ir==t_start(my_rank)) then
1825 : my_rows(1) = it
1826 : my_cols(1) = itp
1827 : end if
1828 : if (ir==t_stop(my_rank)) then
1829 : my_rows(2) = it
1830 : my_cols(2) = itp
1831 : end if
1832 : end do
1833 : end do
1834 :
1835 : ! Allocate big (scalable) buffer to store the BS matrix on this node.
1836 : !ABI_MALLOC(my_bsham,(t_start(my_rank):t_stop(my_rank)))
1837 : !
1838 : ! =====================
1839 : ! === Exchange term ===
1840 : ! =====================
1841 : ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
1842 : ! TODO might used enlarged G-sphere for better convergence.
1843 : !if (do_exchange_term) then
1844 : call timab(683,1,tsec) ! exc_build_ham(exchange)
1845 :
1846 : ABI_MALLOC(rhotwg1,(npweps))
1847 : ABI_MALLOC(rhotwg2,(npweps))
1848 :
1849 : ngx = Gsph_x%ng
1850 : ABI_MALLOC(vc_sqrt_qbz,(ngx))
1851 :
1852 : ! * Get iq_ibz, and symmetries from iq_bz.
1853 : iq_bz = iqbz0 ! q = 0 -> iqbz0
1854 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
1855 :
1856 : ! * Set up table of |q(BZ)+G|
1857 : if (iq_ibz==1) then
1858 : do ig=1,ngx
1859 : ISg = Gsph_x%rottb(ig,itim_q,isym_q)
1860 : vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
1861 : end do
1862 : else
1863 : ABI_ERROR("iq_ibz should be 1")
1864 : end if
1865 :
1866 : do itp=1,BSp%nreh(block) ! Loop over transition tp = (kp,vp,cp,spin2)
1867 :
1868 : if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
1869 : ikp_bz = Bsp%Trans(itp,spin2)%k
1870 : ivp = Bsp%Trans(itp,spin2)%v
1871 : icp = Bsp%Trans(itp,spin2)%c
1872 :
1873 : ikp_ibz = Kmesh%tab (ikp_bz)
1874 : isym_kp = Kmesh%tabo(ikp_bz)
1875 : itim_kp = (3-Kmesh%tabi(ikp_bz))/2
1876 :
1877 : if (is_resonant) then
1878 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
1879 : else ! Code for coupling block.
1880 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
1881 : end if
1882 : !
1883 : ! Multiply by the Coulomb term.
1884 : do ig=2,npweps
1885 : rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
1886 : end do
1887 :
1888 : do it=1,itp ! Loop over transition t = (k,v,c,spin1)
1889 : ir = it + itp*(itp-1_i8b)/2
1890 : if (ir<t_start(my_rank) .or. ir>t_stop(my_rank)) CYCLE
1891 :
1892 : ik_bz = Bsp%Trans(it,spin1)%k
1893 : iv = Bsp%Trans(it,spin1)%v
1894 : ic = Bsp%Trans(it,spin1)%c
1895 :
1896 : ik_ibz = Kmesh%tab(ik_bz)
1897 : isym_k = Kmesh%tabo(ik_bz)
1898 : itim_k = (3-Kmesh%tabi(ik_bz))/2
1899 : !if (itim_k==2) CYCLE ! time-reversal or not
1900 :
1901 : rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
1902 : !
1903 : ! sum over G/=0
1904 : ctemp = xdotc(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
1905 : ctemp = faq * kx_fact * ctemp
1906 :
1907 : ! exchange term is non divergent !
1908 : !if (BSp%prep_interp) then
1909 : ! ccoeffs(ir) = ccoeffs(ir) + ctemp
1910 : !end if
1911 :
1912 : my_bsham(ir) = my_bsham(ir) + ctemp
1913 : end do !it
1914 : end do !itp
1915 :
1916 : ABI_FREE(rhotwg1)
1917 : ABI_FREE(rhotwg2)
1918 : ABI_FREE(vc_sqrt_qbz)
1919 :
1920 : call timab(683,2,tsec) ! exc_build_ham(exchange)
1921 : !end if ! do_exchange_term
1922 : end do ! block
1923 :
1924 : !
1925 : ! ===========================================
1926 : ! === Exchange term for spin_up spin_down ===
1927 : ! ===========================================
1928 :
1929 : if (nsppol==2) then
1930 : call timab(686,2,tsec) ! exc_build_ham(exch.spin)
1931 : block=3
1932 : neh1=BSp%nreh(1)
1933 : neh2=BSp%nreh(2)
1934 : !
1935 : ! The oscillators at q=0 are available on each node for both spin.
1936 : ! Here the calculation of the block is parallelized over columns.
1937 : ABI_MALLOC(col_start,(0:nproc-1))
1938 : ABI_MALLOC(col_stop,(0:nproc-1))
1939 : call xmpi_split_work2_i4b(neh2,nproc,col_start,col_stop) !check this but it should be OK.
1940 :
1941 : my_cols(1) = col_start(my_rank)
1942 : my_cols(2) = col_stop (my_rank)
1943 : if (my_cols(2)-my_cols(1)<=0) then
1944 : ABI_ERROR("One of the processors has zero columns!")
1945 : end if
1946 :
1947 : ABI_MALLOC(ncols_of,(0:nproc-1))
1948 : ncols_of=0
1949 : do rank=0,nproc-1
1950 : if (col_stop(rank)>=col_start(rank)) ncols_of(rank) = col_stop(rank)-col_start(rank)+1
1951 : end do
1952 :
1953 : ABI_FREE(col_start)
1954 : ABI_FREE(col_stop)
1955 : !
1956 : ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
1957 : ! TODO might used enlarged G-sphere for better convergence.
1958 : ! Note that my_kxssp is always written on file when nsppol=2, even when
1959 : ! non-local field effects are neglected.
1960 : ABI_MALLOC(my_kxssp,(neh1,my_cols(1):my_cols(2)))
1961 : my_kxssp=czero
1962 :
1963 : !if (do_exchange_term) then
1964 : !spin1=1; spin2=2
1965 : ABI_MALLOC(rhotwg1,(npweps))
1966 : ABI_MALLOC(rhotwg2,(npweps))
1967 :
1968 : ngx = Gsph_x%ng
1969 : ABI_MALLOC(vc_sqrt_qbz,(ngx))
1970 : !
1971 : ! * Get iq_ibz, and symmetries from iq_bz.
1972 : iq_bz = iqbz0 ! q = 0 -> iqbz0
1973 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
1974 : !
1975 : ! * Set up table of |q(BZ)+G|
1976 : if (iq_ibz==1) then
1977 : do ig=1,ngx
1978 : ISg = Gsph_x%rottb(ig,itim_q,isym_q)
1979 : vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
1980 : end do
1981 : else
1982 : ABI_ERROR("iq_ibz should be 1")
1983 : end if
1984 :
1985 : do itp=1,neh2 ! Loop over transition tp = (kp,vp,cp,spin2)
1986 :
1987 : if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
1988 : ikp_bz = Bsp%Trans(itp,spin2)%k
1989 : ivp = Bsp%Trans(itp,spin2)%v
1990 : icp = Bsp%Trans(itp,spin2)%c
1991 :
1992 : ikp_ibz = Kmesh%tab (ikp_bz)
1993 : isym_kp = Kmesh%tabo(ikp_bz)
1994 : itim_kp = (3-Kmesh%tabi(ikp_bz))/2
1995 :
1996 : if (is_resonant) then
1997 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
1998 : else ! Code for coupling block.
1999 : rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
2000 : end if
2001 : !
2002 : ! Multiply by the Coulomb term.
2003 : do ig=2,npweps
2004 : rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
2005 : end do
2006 :
2007 : do it=1,neh1 ! Loop over transition t = (k,v,c,spin1) FULL matrix.
2008 : ik_bz = Bsp%Trans(it,spin1)%k
2009 : iv = Bsp%Trans(it,spin1)%v
2010 : ic = Bsp%Trans(it,spin1)%c
2011 :
2012 : ik_ibz = Kmesh%tab(ik_bz)
2013 : isym_k = Kmesh%tabo(ik_bz)
2014 : itim_k = (3-Kmesh%tabi(ik_bz))/2
2015 : !if (itim_k==2) CYCLE ! time-reversal or not
2016 :
2017 : rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
2018 : !
2019 : ! sum over G/=0
2020 : ctemp = XDOTC(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
2021 : ctemp = faq * kx_fact * ctemp
2022 :
2023 : my_kxssp(it,itp) = ctemp
2024 : end do !it
2025 : end do !itp
2026 :
2027 : ABI_FREE(rhotwg1)
2028 : ABI_FREE(rhotwg2)
2029 : ABI_FREE(vc_sqrt_qbz)
2030 : !end if ! do_exchange_term
2031 : call timab(686,2,tsec) ! exc_build_ham(exch.spin)
2032 :
2033 : ABI_FREE(ncols_of)
2034 : ABI_SFREE(my_kxssp)
2035 : end if
2036 :
2037 : DBG_EXIT("COLL")
2038 :
2039 : end subroutine exc_build_v
2040 : !!***
2041 :
2042 : !!****f* m_exc_build/exc_build_ham
2043 : !! NAME
2044 : !! exc_build_ham
2045 : !!
2046 : !! FUNCTION
2047 : !! Calculate and write the excitonic Hamiltonian on an external binary file (Fortran binary file)
2048 : !! for subsequent treatment in the Bethe-Salpeter code.
2049 : !!
2050 : !! INPUTS
2051 : !! BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
2052 : !! BS_files<excfiles>=File names internally used in the BS code.
2053 : !! Cryst<crystal_t>=Info on the crystalline structure.
2054 : !! Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
2055 : !! Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
2056 : !! ktabr(nfftot_osc,BSp%nkbz)=The FFT index of $(R^{-1}(r-\tau))$ where R is symmetry needed to obtains
2057 : !! the k-points from the irreducible image. Used to symmetrize u_Sk where S = \transpose R^{-1}
2058 : !! Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
2059 : !! Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
2060 : !! Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
2061 : !! screen<screen_t>=Data type gathering info and data for W.
2062 : !! nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
2063 : !! ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
2064 : !! Psps<Pseudopotential_type>=Variables related to pseudopotentials
2065 : !! Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
2066 : !! Pawang<pawang_type>=PAW angular mesh and related data.
2067 : !! Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite mat. elements of a plane wave.
2068 : !! Wfd<wfdgw_t>=Handler for the wavefunctions.
2069 : !!
2070 : !! OUTPUT
2071 : !! The excitonic Hamiltonian is saved on an external binary file (see below).
2072 : !!
2073 : !! SOURCE
2074 :
2075 29 : subroutine exc_build_ham(BSp,BS_files,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
2076 29 : Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff)
2077 :
2078 : !Arguments ------------------------------------
2079 : !scalars
2080 : integer,intent(in) :: nfftot_osc
2081 : type(excparam),intent(in) :: BSp
2082 : type(excfiles),intent(in) :: BS_files
2083 : type(screen_t),intent(inout) :: screen
2084 : type(kmesh_t),intent(in) :: Kmesh,Qmesh
2085 : type(crystal_t),intent(in) :: Cryst
2086 : type(vcoul_t),intent(in) :: Vcp
2087 : type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
2088 : type(Pseudopotential_type),intent(in) :: Psps
2089 : type(Hdr_type),intent(inout) :: Hdr_bse
2090 : type(pawang_type),intent(in) :: Pawang
2091 : type(wfdgw_t),target,intent(inout) :: Wfd
2092 : !arrays
2093 : integer,intent(in) :: ngfft_osc(18)
2094 : integer,intent(in) :: ktabr(nfftot_osc,Kmesh%nbz)
2095 : type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat*Wfd%usepaw)
2096 : type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
2097 :
2098 : !Local variables ------------------------------
2099 : !scalars
2100 : logical :: do_resonant,do_coupling
2101 : !character(len=500) :: msg
2102 : !arrays
2103 : real(dp) :: tsec(2)
2104 29 : complex(gwp),allocatable :: all_mgq0(:,:,:,:,:)
2105 : !************************************************************************
2106 :
2107 29 : call timab(670,1,tsec)
2108 :
2109 29 : ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
2110 116 : ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
2111 :
2112 29 : if (BSp%have_complex_ene) then
2113 0 : ABI_ERROR("Complex energies are not supported yet")
2114 : end if
2115 :
2116 : ! Do we have to compute some block?
2117 29 : do_resonant = (BS_files%in_hreso == BSE_NOFILE)
2118 29 : do_coupling = (BS_files%in_hcoup == BSE_NOFILE)
2119 :
2120 29 : if (BSp%use_coupling == 0) then
2121 28 : if (.not.do_resonant) then
2122 6 : call wrtout(std_out,"Will skip the calculation of resonant block (will use BSR file)")
2123 6 : goto 100
2124 : end if
2125 : else
2126 1 : if (.not. do_resonant .and. .not. do_coupling) then
2127 0 : call wrtout(std_out,"Will skip the calculation of both resonant and coupling block (will use BSR and BSC files)")
2128 0 : goto 100
2129 : end if
2130 : end if
2131 :
2132 : ! Compute M_{k,q=0}^{b,b}(G) for all k-points in the IBZ and each pair b, b'
2133 : ! used for the exchange part and part of the Coulomb term.
2134 23 : call wrtout(std_out," Calculating all matrix elements for q=0 to save CPU time")
2135 :
2136 : call wfd_all_mgq0(Wfd,Cryst,Qmesh,Gsph_x,Vcp,Psps,Pawtab,Paw_pwff,&
2137 23 : Bsp%lomo_spin,Bsp%homo_spin,Bsp%humo_spin,nfftot_osc,ngfft_osc,Bsp%npweps,all_mgq0)
2138 :
2139 : ! ========================
2140 : ! ==== Resonant Block ====
2141 : ! ========================
2142 23 : if (do_resonant) then
2143 22 : call timab(672,1,tsec)
2144 : call exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
2145 22 : Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,all_mgq0,.TRUE.,BS_files%out_hreso)
2146 22 : call timab(672,2,tsec)
2147 : end if
2148 :
2149 : ! ========================
2150 : ! ==== Coupling Block ====
2151 : ! ========================
2152 23 : if (do_coupling .and. BSp%use_coupling > 0) then
2153 1 : call timab(673,1,tsec)
2154 : call exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
2155 1 : Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,all_mgq0,.FALSE.,BS_files%out_hcoup)
2156 1 : call timab(673,2,tsec)
2157 : end if
2158 :
2159 : ! Free memory.
2160 23 : ABI_FREE(all_mgq0)
2161 :
2162 29 : 100 call timab(670,2,tsec)
2163 :
2164 29 : end subroutine exc_build_ham
2165 : !!***
2166 :
2167 : !!****f* m_exc_build/wfd_all_mgq0
2168 : !! NAME
2169 : !! wfd_all_mgq0
2170 : !!
2171 : !! FUNCTION
2172 : !!
2173 : !! INPUTS
2174 : !! Wfd<wfdgw_t>=Handler for the wavefunctions.
2175 : !! Cryst<crystal_t>=Info on the crystalline structure.
2176 : !! Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
2177 : !! Gsph_x<gsphere_t>=G-sphere with the G-vectors in mgq0.
2178 : !! Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
2179 : !! Psps<Pseudopotential_type>=Variables related to pseudopotentials
2180 : !! Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
2181 : !! Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite mat. elements of a plane wave.
2182 : !! lomo_spin(Wfd%nsppol)=Lowest occupied band for each spin
2183 : !! homo_spin(Wfd%nsppol)=Highest occupied band for each spin
2184 : !! humo_spin(Wfd%nsppol)=Highest unoccupied band for each spin
2185 : !! nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
2186 : !! ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
2187 : !! npweps=Number of G-vectors in mgq0.
2188 : !!
2189 : !! OUTPUT
2190 : !! mgq0(npweps,lomo_min:humo_max,lomo_min:humo_max,Wfd%nkibz,Wfd%nsppol)
2191 : !! Allocated here and filled with the matrix elements on each node.
2192 : !!
2193 : !! SOURCE
2194 :
2195 23 : subroutine wfd_all_mgq0(Wfd,Cryst,Qmesh,Gsph_x,Vcp,&
2196 23 : & Psps,Pawtab,Paw_pwff,lomo_spin,homo_spin,humo_spin,nfftot_osc,ngfft_osc,npweps,mgq0)
2197 :
2198 : !Arguments ------------------------------------
2199 : !scalars
2200 : integer,intent(in) :: nfftot_osc,npweps
2201 : type(kmesh_t),intent(in) :: Qmesh
2202 : type(crystal_t),intent(in) :: Cryst
2203 : type(vcoul_t),intent(in) :: Vcp
2204 : type(gsphere_t),intent(in) :: Gsph_x
2205 : type(Pseudopotential_type),intent(in) :: Psps
2206 : type(wfdgw_t),target,intent(inout) :: Wfd
2207 : !arrays
2208 : integer,intent(in) :: lomo_spin(Wfd%nsppol),homo_spin(Wfd%nsppol),humo_spin(Wfd%nsppol)
2209 : integer,intent(in) :: ngfft_osc(18)
2210 : complex(gwp),allocatable,intent(out) :: mgq0(:,:,:,:,:)
2211 : type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat)
2212 : type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
2213 :
2214 : !Local variables ------------------------------
2215 : !scalars
2216 : integer,parameter :: map2sphere1=1,dim_rtwg1=1,ndat1=1
2217 : integer :: use_padfft,mgfft_osc,fftalga_osc,ii
2218 : integer :: ik_ibz,itim_k,isym_k,iq_bz,iq_ibz,isym_q,itim_q,iqbz0
2219 : integer :: ierr,iv,ic,spin,lomo_min,humo_max !,inv_ipw,ipw
2220 : real(dp) :: cpu,wall,gflops !q0vol,fcc_const
2221 : complex(dp) :: ph_mkt
2222 : character(len=500) :: msg
2223 : type(wave_t),pointer :: wave_v, wave_c
2224 : !arrays
2225 23 : integer,allocatable :: igfftg0(:),task_distrib(:,:,:,:)
2226 23 : integer,allocatable :: gbound(:,:),id_tab(:)
2227 : real(dp) :: qbz(3),spinrot_k(4),tsec(2)
2228 23 : complex(gwp),allocatable :: rhotwg1(:)
2229 23 : complex(gwp),target,allocatable :: ur1(:),ur2(:)
2230 23 : complex(gwp),contiguous, pointer :: ptr_ur1(:),ptr_ur2(:)
2231 23 : type(pawcprj_type),allocatable :: Cp1(:,:),Cp2(:,:)
2232 23 : type(pawpwij_t),allocatable :: Pwij_q0(:)
2233 : !************************************************************************
2234 :
2235 23 : call timab(671,1,tsec)
2236 :
2237 23 : ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
2238 92 : ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
2239 :
2240 71 : lomo_min = MINVAL(lomo_spin); humo_max = MAXVAL(humo_spin)
2241 :
2242 50 : if ( ANY(ngfft_osc(1:3) /= Wfd%ngfft(1:3)) ) call wfd%change_ngfft(Cryst,Psps,ngfft_osc)
2243 :
2244 92 : mgfft_osc = MAXVAL(ngfft_osc(1:3))
2245 23 : fftalga_osc = ngfft_osc(7)/100 !; fftalgc_osc=MOD(ngfft_osc(7),10)
2246 :
2247 : ! (temporary) Table used for the wavefunction in the IBZ.
2248 69 : ABI_MALLOC(id_tab, (Wfd%nfft))
2249 482671 : id_tab = (/(ii, ii=1,Wfd%nfft)/)
2250 :
2251 : ! Analytic integration of 4pi/q^2 over the volume element:
2252 : ! $4pi/V \int_V d^3q 1/q^2 =4pi bz_geometric_factor V^(-2/3)$
2253 : ! i_sz=4*pi*bz_geometry_factor*q0_vol**(-two_thirds) where q0_vol= V_BZ/N_k
2254 : ! bz_geometry_factor: sphere=7.79, fcc=7.44, sc=6.188, bcc=6.946, wz=5.255
2255 : ! (see gwa.pdf, appendix A.4)
2256 :
2257 : ! If q=0 and C=V then set up rho-twiddle(G=0) to reflect an
2258 : ! analytic integration of q**-2 over the volume element:
2259 : ! <q**-2> = 7.44 V**(-2/3) (for fcc cell)
2260 :
2261 : ! q0vol = (8.0*pi**3) / (Cryst%ucvol*Kmesh%nbz)
2262 : ! fcc_const = SQRT(7.44*q0vol**(-2.0/3.0))
2263 : ! rtw = (6.0*pi**2/(Cryst%ucvol*Kmesh%nkbz))**(1./3.)
2264 : ! Average of (q+q')**-2 integration for head of Coulomb matrix
2265 : ! INTRTW(QL) = (2*pi*rtw + pi*(rtw**2/QL-QL)*LOG((QL+rtw)/(QL-rtw)))
2266 : ! & * (Cryst%ucvol*Kmesh%nbz)/(2*pi)**3. * QL*QL
2267 :
2268 23 : if (Wfd%usepaw==1) then
2269 14 : ABI_MALLOC(Cp1,(Wfd%natom,Wfd%nspinor))
2270 2 : call pawcprj_alloc(Cp1,0,Wfd%nlmn_atm)
2271 14 : ABI_MALLOC(Cp2,(Wfd%natom,Wfd%nspinor))
2272 2 : call pawcprj_alloc(Cp2,0,Wfd%nlmn_atm)
2273 : end if
2274 :
2275 69 : ABI_MALLOC(ur1,(nfftot_osc*Wfd%nspinor))
2276 46 : ABI_MALLOC(ur2,(nfftot_osc*Wfd%nspinor))
2277 :
2278 : ! Identify q==0
2279 23 : iqbz0=0
2280 1079 : do iq_bz=1,Qmesh%nbz
2281 1446 : if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
2282 : end do
2283 23 : ABI_CHECK(iqbz0/=0,"q=0 not found in q-point list!")
2284 :
2285 : ! * Get iq_ibz, and symmetries from iqbz0.
2286 23 : call qmesh%get_BZ_item(iqbz0,qbz,iq_ibz,isym_q,itim_q)
2287 :
2288 23 : if (Wfd%usepaw==1) then ! Prepare onsite contributions at q==0
2289 9 : ABI_MALLOC(Pwij_q0,(Cryst%ntypat))
2290 2 : call pawpwij_init(Pwij_q0,npweps,Qmesh%bz(:,iqbz0),Gsph_x%gvec,Cryst%rprimd,Psps,Pawtab,Paw_pwff)
2291 : end if
2292 : !
2293 : ! Tables for the FFT of the oscillators.
2294 : ! a) FFT index of the G sphere (only vertical transitions, unlike cchi0, no need to shift the sphere).
2295 : ! b) gbound table for the zero-padded FFT performed in rhotwg.
2296 69 : ABI_MALLOC(igfftg0,(Gsph_x%ng))
2297 92 : ABI_MALLOC(gbound,(2*mgfft_osc+8,2))
2298 23 : call Gsph_x%fft_tabs((/0,0,0/),mgfft_osc,ngfft_osc,use_padfft,gbound,igfftg0)
2299 23 : if ( ANY(fftalga_osc == (/2,4/)) ) use_padfft=0 ! Pad-FFT is not coded in rho_tw_g
2300 23 : if (use_padfft==0) then
2301 0 : ABI_FREE(gbound)
2302 0 : ABI_MALLOC(gbound,(2*mgfft_osc+8,2*use_padfft))
2303 : end if
2304 :
2305 69 : ABI_MALLOC(rhotwg1,(npweps))
2306 :
2307 161 : ABI_MALLOC_OR_DIE(mgq0, (npweps,lomo_min:humo_max,lomo_min:humo_max,Wfd%nkibz,Wfd%nsppol), ierr)
2308 1317080 : mgq0 = czero
2309 :
2310 23 : call cwtime(cpu,wall,gflops,"start")
2311 :
2312 47 : do spin=1,Wfd%nsppol
2313 : ! Distribute the calculation of the matrix elements.
2314 : ! processors have the entire set of wavefunctions hence we divide the workload
2315 : ! without checking if the pair of states is available. Last dimension is fake.
2316 120 : ABI_MALLOC(task_distrib,(lomo_spin(spin):humo_spin(spin),lomo_spin(spin):humo_spin(spin),Wfd%nkibz,1))
2317 24 : call xmpi_distab(Wfd%nproc,task_distrib)
2318 :
2319 : ! loop over the k-points in IBZ
2320 887 : do ik_ibz=1,Wfd%nkibz
2321 8543 : if ( ALL(task_distrib(:,:,ik_ibz,1)/= Wfd%my_rank) ) CYCLE
2322 :
2323 : ! Don't need to symmetrize the wavefunctions.
2324 3035 : itim_k=1; isym_k=1; ph_mkt=cone; spinrot_k=Cryst%spinrot(:,isym_k)
2325 :
2326 4109 : do iv=lomo_spin(spin),humo_spin(spin) ! Loop over band V
2327 3478 : if ( ALL(task_distrib(:,iv,ik_ibz,1)/=Wfd%my_rank) ) CYCLE
2328 :
2329 3478 : ABI_CHECK(wfd%get_wave_ptr(iv, ik_ibz, spin, wave_v, msg) == 0, msg)
2330 :
2331 3478 : if (wave_v%has_ur == WFD_STORED) then
2332 2989 : ptr_ur1 => wave_v%ur
2333 : else
2334 489 : call wfd%get_ur(iv,ik_ibz,spin,ur1)
2335 489 : ptr_ur1 => ur1
2336 : end if
2337 :
2338 3478 : if (Wfd%usepaw==1) call wfd%get_cprj(iv,ik_ibz,spin,Cryst,Cp1,sorted=.FALSE.)
2339 :
2340 : ! Loop over band C
2341 24829 : do ic=lomo_spin(spin),humo_spin(spin)
2342 20488 : if ( task_distrib(ic,iv,ik_ibz,1)/=Wfd%my_rank ) CYCLE
2343 :
2344 20488 : ABI_CHECK(wfd%get_wave_ptr(ic, ik_ibz, spin, wave_c, msg) == 0, msg)
2345 :
2346 20488 : if (wave_c%has_ur == WFD_STORED) then
2347 17853 : ptr_ur2 => wave_c%ur
2348 : else
2349 2635 : call wfd%get_ur(ic,ik_ibz,spin,ur2)
2350 2635 : ptr_ur2 => ur2
2351 : end if
2352 :
2353 20488 : if (Wfd%usepaw==1) call wfd%get_cprj(ic,ik_ibz,spin,Cryst,Cp2,sorted=.FALSE.)
2354 :
2355 : call rho_tw_g(Wfd%nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere1,use_padfft,igfftg0,gbound,&
2356 : ptr_ur1,1,id_tab,ph_mkt,spinrot_k,&
2357 : ptr_ur2,1,id_tab,ph_mkt,spinrot_k,&
2358 20488 : dim_rtwg1,rhotwg1)
2359 :
2360 20488 : if (Wfd%usepaw==1) then
2361 : ! Add PAW onsite contribution.
2362 304 : call paw_rho_tw_g(cryst,Pwij_q0,npweps,dim_rtwg1,Wfd%nspinor,Gsph_x%gvec,Cp1,Cp2,rhotwg1)
2363 : end if
2364 :
2365 : ! If q=0 treat Exchange and Coulomb-term independently
2366 20488 : if (iv <= homo_spin(spin) .and. ic <= homo_spin(spin) .or. &
2367 : iv > homo_spin(spin) .and. ic > homo_spin(spin)) then
2368 :
2369 10424 : if (iv/=ic) then !COULOMB term: C/=V: ignore them
2370 6946 : rhotwg1(1) = czero_gw
2371 : else
2372 : ! If q=0 and C=V then set up rho-twiddle(G=0) to reflect an
2373 : ! analytic integration of q**-2 over the volume element:
2374 : ! <q**-2> = 7.44 V**(-2/3) (for fcc cell)
2375 : !rhotwg1(1) = fcc_const * qpg(1,iqbz0)
2376 3478 : rhotwg1(1) = SQRT(GWPC_CMPLX(Vcp%i_sz,zero)) / Vcp%vcqlwl_sqrt(1,1)
2377 : !if (vcut) rhotwg1(1) = 1.0
2378 : end if
2379 :
2380 : else
2381 : ! At present this term is set to zero
2382 : ! EXCHANGE term: limit value.
2383 : ! Set up rho-twiddle(G=0) using small vector q instead of zero and k.p perturbation theory (see notes)
2384 10064 : rhotwg1(1) = czero_gw
2385 : end if
2386 :
2387 930890 : mgq0(:,iv,ic,ik_ibz,spin) = rhotwg1(:)
2388 : end do !ic
2389 : end do !iv
2390 : end do !ik_ibz
2391 :
2392 47 : ABI_FREE(task_distrib)
2393 : end do !spin
2394 :
2395 : ! TODO: One can speedup the calculation by computing the upper triangle of the
2396 : ! matrix in (b,b') space and then take advantage of the symmetry property:
2397 : !
2398 : ! M_{k,0}{{bb'}(G)^* = M{k,0}{b'b'}(-G)
2399 :
2400 : #if 0
2401 : !!!! $OMP PARALLEL DO COLLAPSE(3) PRIVATE(inv_ipw)
2402 : do spin=1,Wfd%nsppol
2403 : do ik_ibz=1,Wfd%nkibz
2404 : do iv=lomo_spin(spin),humo_spin(spin)
2405 : do ic=1,iv-1
2406 : do ipw=1,npweps
2407 : inv_ipw = gsph_x%g2mg(ipw)
2408 : mgq0(inv_ipw,ic,iv,ik_ibz,spin) = mgq0(ipw,iv,ic,ik_ibz,spin)
2409 : end do
2410 : end do
2411 : end do
2412 : end do
2413 : end do
2414 : #endif
2415 : !
2416 : ! Gather matrix elements on each node.
2417 23 : call xmpi_sum(mgq0,Wfd%comm,ierr)
2418 :
2419 23 : call cwtime(cpu,wall,gflops,"stop")
2420 23 : write(msg,'(2(a,f9.6))')"cpu_time = ",cpu,", wall_time = ",wall
2421 23 : call wrtout(std_out, msg)
2422 :
2423 23 : ABI_FREE(rhotwg1)
2424 23 : ABI_FREE(igfftg0)
2425 23 : ABI_FREE(gbound)
2426 23 : ABI_FREE(ur1)
2427 23 : ABI_FREE(ur2)
2428 23 : ABI_FREE(id_tab)
2429 :
2430 23 : if (Wfd%usepaw==1) then
2431 : ! Deallocation for PAW.
2432 2 : call pawpwij_free(Pwij_q0)
2433 5 : ABI_FREE(Pwij_q0)
2434 2 : call pawcprj_free(Cp1)
2435 6 : ABI_FREE(Cp1)
2436 2 : call pawcprj_free(Cp2)
2437 6 : ABI_FREE(Cp2)
2438 : end if
2439 :
2440 23 : call timab(671,2,tsec)
2441 :
2442 92 : end subroutine wfd_all_mgq0
2443 : !!***
2444 :
2445 : end module m_exc_build
2446 : !!***
|