Line data Source code
1 : !!****m* ABINIT/m_vtorhorec
2 : !! NAME
3 : !! m_vtorhorec
4 : !!
5 : !! FUNCTION
6 : !!
7 : !! COPYRIGHT
8 : !! Copyright (C) 2008-2026 ABINIT group (SLeroux, MMancini).
9 : !! This file is distributed under the terms of the
10 : !! GNU General Public License, see ~abinit/COPYING
11 : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : !!
13 : !! SOURCE
14 :
15 : #if defined HAVE_CONFIG_H
16 : #include "config.h"
17 : #endif
18 :
19 : #include "abi_common.h"
20 :
21 : module m_vtorhorec
22 :
23 : use defs_basis
24 : use defs_rectypes
25 : use m_xmpi
26 : use m_pretty_rec
27 : use m_errors
28 : use m_abicore
29 : use m_per_cond
30 : use m_dtset
31 :
32 : use defs_datatypes, only : pseudopotential_type
33 : use defs_abitypes, only : MPI_type
34 : use m_time, only : timein, timab
35 : use m_rec, only : Calcnrec, init_nlpsprec, cpu_distribution
36 : use m_rec_tools, only : reshape_pot, trottersum, get_pt0_pt1
37 : use m_spacepar, only : symrhg
38 : use m_fourier_interpol, only : transgrid
39 : use m_fft, only : fourdp
40 :
41 : #ifdef HAVE_GPU_CUDA
42 : use m_gpu_toolbox
43 : use m_hidecudarec
44 : use m_xredistribute
45 : #endif
46 :
47 : implicit none
48 :
49 : private
50 : !!***
51 :
52 : public :: vtorhorec
53 : public :: first_rec
54 : !!***
55 :
56 : contains
57 : !!***
58 :
59 : !!****f* ABINIT/vtorhorec
60 : !! NAME
61 : !! vtorhorec
62 : !!
63 : !! FUNCTION
64 : !! This routine computes the new density from a fixed potential (vtrial)
65 : !! using a recursion method
66 : !!
67 : !! INPUTS
68 : !! deltastep= if 0 the iteration step is equal to dtset%nstep
69 : !! initialized= if 0 the initialization of the gstate run is not yet finished
70 : !! operator (ground-state symmetries)
71 : !! dtset <type(dataset_type)>=all input variables for this dataset
72 : !! irrzon(nfft**(1-1/nsym),2,(nspden/nsppol)-3*(nspden/4))=irreducible zone data
73 : !! nfftf=(effective) number of FFT grid points (for this processor)
74 : !! nspden=number of spin-density components
75 : !! nsppol=1 for unpolarized, 2 for spin-polarized
76 : !! nsym=number of symmetry elements in space group
77 : !! phnons(2,nfft**(1-1/nsym),(nspden/nsppol)-3*(nspden/4))=nonsymmorphic translation phases
78 : !! vtrial(nfft,nspden)=INPUT Vtrial(r).
79 : !! rset <type(recursion_type)> all variables for recursion
80 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
81 : !! gprimd(3,3)=dimensional primitive translations in reciprocal space
82 : !!
83 : !! OUTPUT
84 : !! ek=kinetic energy part of total energy.
85 : !! enlx=nonlocal psp + potential Fock ACE part of total energy.
86 : !! entropy=entropy due to the occupation number smearing (if metal)
87 : !! e_eigenvalues=Sum of the eigenvalues - Band energy (Hartree)
88 : !! fermie=fermi energy (Hartree)
89 : !! grnl(3*natom)=stores grads of nonlocal energy wrt length scales
90 : !! (3x3 tensor) and grads wrt atomic coordinates (3*natom)
91 : !!
92 : !! SIDE EFFECTS
93 : !! rhog(2,nfft)=array for Fourier transform of electron density
94 : !! rhor(nfft,nspden)=array for electron density in electrons/bohr**3.
95 : !! rset%efermi= fermi energy
96 : !!
97 : !! NOTES
98 : !! at this time :
99 : !! - grnl in not implemented
100 : !! - symetrie usage not implemented (irrzon not used and nsym should be 1)
101 : !! - spin-polarized not implemented (nsppol must be 1, nspden ?)
102 : !! - phnons used only in symrhg
103 : !! - need a rectangular box (ngfft(1)=ngfft(2)=ngfft(3))
104 : !!
105 : !! SOURCE
106 :
107 38 : subroutine vtorhorec(dtset,&
108 : & ek,enlx,entropy,e_eigenvalues,fermie,&
109 76 : & grnl,initialized,irrzon,nfftf,phnons,&
110 76 : & rhog, rhor, vtrial,rset,deltastep,rprimd,gprimd)
111 :
112 : !Arguments -------------------------------
113 : !scalars
114 : integer,intent(in) :: initialized
115 : integer,intent(in) :: nfftf,deltastep
116 : real(dp),intent(out) :: e_eigenvalues,ek,enlx,entropy,fermie
117 : type(dataset_type),intent(in) :: dtset
118 : type(recursion_type),intent(inout) :: rset
119 : !arrays
120 : integer, intent(in) :: irrzon(:,:,:)
121 : real(dp),intent(in) :: rprimd(3,3),gprimd(3,3)
122 : real(dp),intent(in) :: phnons(:,:,:)
123 : real(dp),intent(in) :: vtrial(:,:)
124 : real(dp),intent(inout) :: rhog(:,:)
125 : real(dp),intent(out) :: grnl(:) !vz_i
126 : real(dp),intent(inout) :: rhor(:,:) !vz_i
127 :
128 : !Local variables-------------------------------
129 : !scalars
130 : integer :: nfftrec, dim_entro,ii1,jj1,kk1
131 : integer :: ierr,ii,ilmn,ipsp,dim_trott
132 : integer :: ipoint,ipointlocal,jj,kk,irec
133 : integer :: n1,n2,n3,n4,n_pt_integ_entropy
134 : integer :: nrec,iatom,min_pt,max_pt,swt_tm
135 : integer :: get_K_S_G
136 : integer :: tim_fourdp,trotter
137 : real(dp),parameter :: perc_vmin=one
138 : real(dp) :: beta,drho,drhomax
139 : real(dp) :: entropy1,entropy2,entropy3,entropy4
140 : real(dp) :: entropylocal,entropylocal1,entropylocal2
141 : real(dp) :: entropylocal3,entropylocal4,gran_pot,gran_pot1,gran_pot2
142 : real(dp) :: gran_pot3,gran_pot4,gran_pot_local,gran_pot_local1
143 : real(dp) :: gran_pot_local2,gran_pot_local3,gran_pot_local4
144 : real(dp) :: inf_ucvol,intrhov,factor
145 : real(dp) :: nelect,potmin,rtrotter,toldrho,tolrec,tsmear
146 : real(dp) :: xmax,nlpotmin,ratio1,ratio2,ratio4,ratio8
147 38 : type(recparall_type) :: recpar
148 : character(len=500) :: msg
149 : !arrays
150 : integer :: ngfftrec(18),trasl(3)
151 38 : integer,pointer :: gcart_loc(:,:)
152 38 : integer,allocatable :: bufsize(:), bufdispl(:)
153 : real(dp) :: tsec(2),tsec2(2)
154 76 : real(dp) :: exppot(0:dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3)-1)
155 76 : real(dp),target :: rholocal(1:rset%par%ntranche)
156 76 : real(dp),target :: alocal(0:rset%min_nrec,1:rset%par%ntranche)
157 76 : real(dp),target :: b2local(0:rset%min_nrec,1:rset%par%ntranche)
158 38 : real(dp),pointer :: rho_wrk(:)
159 38 : real(dp),pointer :: a_wrk(:,:),b2_wrk(:,:)
160 38 : real(dp),allocatable :: rholocal_f(:), rholoc_2(:)
161 38 : real(dp),allocatable :: rhogf(:,:),rhogc(:,:),aloc_copy(:,:),b2loc_copy(:,:)
162 38 : real(dp),allocatable :: gran_pot_v_f(:,:),gran_pot_v_c(:,:),gran_pot_v_2(:,:)
163 38 : real(dp),allocatable :: entropy_v_f(:,:),entropy_v_c(:,:),entropy_v_2(:,:)
164 38 : real(dp),allocatable :: ablocal_1(:,:,:),ablocal_2(:,:,:),ablocal_f(:,:,:)
165 38 : real(dp),allocatable :: exppotloc(:)
166 38 : real(dp),allocatable :: projec(:,:,:,:,:)
167 : #if defined HAVE_GPU_CUDA
168 : integer :: max_rec
169 : integer,allocatable :: vcount_0(:), displs_0(:)
170 : integer,allocatable :: vcount_1(:), displs_1(:)
171 : real(dp),allocatable,target :: rho_hyb(:)
172 : real(dp),allocatable,target :: a_hyb(:,:),b2_hyb(:,:)
173 : real(cudap),allocatable :: an_dev(:,:)
174 : real(cudap),allocatable :: bn2_dev(:,:)
175 : #endif
176 :
177 : ! *********************************************************************
178 38 : if(rset%debug)then
179 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' vtorhorec : enter '
180 0 : call wrtout(std_out,msg,'PERS')
181 : end if
182 :
183 38 : call timab(21,1,tsec)
184 38 : call timab(600,1,tsec2)
185 : !##################################################################################################
186 : !!--Initalization in the FIRST time in VTORHOREC is made in SCFCV by FIRST_REC routine
187 : !!--Parameters for the recursion method AND Initialisation
188 :
189 38 : trotter = dtset%recptrott !--trotter parameter
190 38 : nelect = dtset%nelect !--number of electrons
191 :
192 38 : toldrho = dtset%rectolden !--tollerance for density
193 38 : tolrec = toldrho*1.d-2 !--tollerance for local density
194 :
195 38 : tsmear = dtset%tsmear !--temperature
196 38 : beta = one/tsmear !--inverse of temperature
197 :
198 38 : factor = real(dtset%recgratio**3*100*rset%mpi%nproc,dp)/real(nfftf,dp)
199 :
200 : !--Assignation of the rset variable:
201 38 : nrec = rset%min_nrec
202 38 : nfftrec = rset%nfftrec
203 722 : ngfftrec = rset%ngfftrec
204 38 : inf_ucvol = rset%inf%ucvol
205 :
206 38 : min_pt = rset%par%displs(rset%mpi%me)+1
207 38 : max_pt = min_pt+rset%par%vcount(rset%mpi%me)-1
208 :
209 : !--In the last self-constistent loop or if density is converged the
210 : !thermodynamics quantities are calculated
211 38 : get_K_S_G = 0; if(deltastep==0 .or. rset%quitrec/=0) get_K_S_G = 1;
212 :
213 : !--Rewriting the trotter parameter
214 38 : rtrotter = max(half,real(trotter,dp))
215 38 : dim_trott = max(0,2*trotter-1)
216 :
217 : !--Variables Optimisation
218 38 : ratio1 = beta/rtrotter
219 38 : ratio2 = ratio1/two
220 38 : ratio4 = ratio1/four
221 38 : ratio8 = ratio1/eight
222 :
223 : !--Integration points for entropy
224 38 : n_pt_integ_entropy = max(25,dtset%recnpath)
225 :
226 : !-- energies non-local: at day not implemented
227 38 : enlx = zero
228 467 : grnl = zero
229 : !jmb
230 38 : ek = zero
231 :
232 : !--only a copy of ngfft(1:3) and nfft (to purge!!)
233 38 : n1 = dtset%ngfft(1) ; n2 = dtset%ngfft(2) ; n3 = dtset%ngfft(3)
234 38 : n4 = n3
235 :
236 : !--time switch to measure gpu-cpu syncrhonisation
237 38 : swt_tm = 0 ; !no gpu initally
238 :
239 65702 : exppot = zero
240 38 : nullify(gcart_loc)
241 :
242 38 : if(dtset%rectesteg==1)then
243 : ! --Free electron gas case
244 5187 : exppot = one
245 : else
246 35 : if(.not.(rset%nl%nlpsp)) then
247 : ! --Local case
248 : ! --COMPUTATION OF exp( -beta*pot/(4*rtrotter))
249 35 : ABI_MALLOC(gcart_loc,(0,0))
250 : gcart_loc = 0
251 60515 : exppot = exp( -(ratio4*vtrial(:,1)))
252 : else
253 : ! --Non-Local case
254 : ! --COMPUTATION OF exp(-beta*pot/(8*rtrotter))
255 0 : exppot = exp( -(ratio8*vtrial(:,1)))
256 :
257 0 : ABI_MALLOC(gcart_loc,(3,dtset%natom))
258 0 : gcart_loc = rset%inf%gcart
259 0 : ABI_MALLOC(projec,(0:ngfftrec(1)-1,0:ngfftrec(2)-1,0:ngfftrec(3)-1,rset%nl%lmnmax,dtset%natom))
260 0 : projec = zero
261 :
262 0 : if(.not.(rset%tronc)) then
263 0 : do iatom =1, dtset%natom
264 0 : ipsp = dtset%typat(iatom)
265 0 : do ilmn = 1,rset%nl%lmnmax
266 0 : projec(:,:,:,ilmn,iatom) = reshape(rset%nl%projec(:,ilmn,ipsp),shape=shape(projec(:,:,:,1,1)))
267 0 : do ii=1,3
268 0 : projec(:,:,:,ilmn,iatom) = cshift(projec(:,:,:,ilmn,iatom),shift=ngfftrec(ii)/2-gcart_loc(ii,iatom),dim=ii)
269 : end do
270 : end do
271 : end do
272 : end if
273 : end if
274 : end if
275 :
276 : !###################################################################################
277 : !MAIN LOOP
278 :
279 955622 : rholocal = zero; alocal = zero; b2local = zero
280 38 : ipointlocal = 1
281 :
282 : !--Allocation: if hybrid calculation is done then I have to use
283 : !balanced work on devices.
284 38 : nullify(rho_wrk,a_wrk,b2_wrk)
285 :
286 38 : if(rset%load == 1)then
287 : #ifdef HAVE_GPU_CUDA
288 : ABI_MALLOC(rho_hyb,(1:rset%GPU%par%npt))
289 : ABI_MALLOC(a_hyb,(0:nrec,1:rset%GPU%par%npt))
290 : ABI_MALLOC(b2_hyb,(0:nrec,1:rset%GPU%par%npt))
291 : rho_hyb = zero; a_hyb = zero; b2_hyb = zero
292 : rho_wrk => rho_hyb
293 : a_wrk => a_hyb
294 : b2_wrk => b2_hyb
295 : recpar = rset%GPU%par
296 : #endif
297 : else
298 38 : rho_wrk => rholocal
299 38 : a_wrk => alocal
300 38 : b2_wrk => b2local
301 38 : recpar = rset%par
302 : end if
303 :
304 : !#if defined HAVE_GPU_CUDA
305 : !if(rset%debug)then
306 : !write (std_out,*) 'rset%recGPU%nptrec ',rset%recGPU%nptrec
307 : !write (std_out,*) 'rset%gpudevice ',rset%gpudevice
308 : !write (std_out,*) 'rset%ngfftrec ',rset%ngfftrec(1:3)
309 : !write (std_out,*) 'rset%min_nrec ',rset%min_nrec
310 : !write (std_out,*) 'rset%par%ntranche ',rset%par%ntranche
311 : !write (std_out,*) 'rset%par%min_pt ',rset%par%min_pt,min_pt
312 : !write (std_out,*) 'rset%par%max_pt ',rset%par%max_pt,max_pt
313 : !write (std_out,*) 'pt0 ',rset%par%pt0%x,rset%par%pt0%y,rset%par%pt0%z
314 : !write (std_out,*) 'pt1 ',rset%par%pt1%x,rset%par%pt1%y,rset%par%pt1%z
315 : !end if
316 : !#endif
317 :
318 38 : if(rset%gpudevice>=0) then
319 : #if defined HAVE_GPU_CUDA
320 : swt_tm = 1;
321 : call timab(607,1,tsec2)
322 : ABI_MALLOC(an_dev,(0:recpar%npt-1,0:nrec))
323 : ABI_MALLOC(bn2_dev,(0:recpar%npt-1,0:nrec))
324 : an_dev = zero
325 : bn2_dev = zero; bn2_dev(:,0) = one
326 :
327 : call cudarec( rset, exppot,an_dev,bn2_dev,&
328 : & beta,trotter,tolrec,dtset%recgratio,dtset%ngfft(:3),max_rec)
329 :
330 : max_rec = min(max_rec,nrec)
331 : a_wrk(0:max_rec,1:recpar%npt) = transpose(an_dev(0:,0:max_rec))
332 : b2_wrk(0:max_rec,1:recpar%npt) = transpose(bn2_dev(0:,0:max_rec))
333 :
334 : ABI_FREE(an_dev)
335 : ABI_FREE(bn2_dev)
336 : call timab(607,2,tsec2)
337 :
338 : ipointlocal = recpar%npt+1
339 :
340 : ! !DEBUG CUDA
341 : ! if(rset%debug)then
342 : ! if( rset%mpi%me==0)then
343 : ! do ipoint = 1,rset%par%npt,1
344 : ! kk=ipoint/(product(dtset%ngfft(:2)))
345 : ! jj=ipoint/dtset%ngfft(1)-kk*dtset%ngfft(2)
346 : ! ii=ipoint-jj*dtset%ngfft(1)-kk*dtset%ngfft(2)*dtset%ngfft(1)
347 : ! write(msg,'(a,4i8,2(a,a9,5f12.6))')&
348 : ! & 'pt',ipoint,ii,jj,kk,&
349 : ! & ch10,'an-gpu ',real(alocal(:4,ipoint)),&
350 : ! & ch10,'b2n-gpu ',real(b2local(:4,ipoint))
351 : ! call wrtout(std_out,msg,'COLL')
352 : ! end do
353 : ! endif
354 : ! endif
355 : ! !ENDDEBUG CUDA
356 : #endif
357 :
358 : else
359 38 : if (.not.(rset%tronc)) then
360 120 : graou1 : do kk = recpar%pt0%z,recpar%pt1%z,dtset%recgratio
361 1560 : do jj = 0,n2-1,dtset%recgratio
362 18778 : do ii = 0,n1-1,dtset%recgratio
363 17280 : ipoint = ii+(jj+kk*n2)*n1
364 : ! --Local position of atoms
365 17280 : if (ipoint<recpar%min_pt) cycle
366 : ! --Computation done by that proc
367 17280 : tim_fourdp=6
368 : call recursion(exppot,ii,jj,kk, &
369 : & a_wrk(:,ipointlocal), &
370 : & b2_wrk(:,ipointlocal), &
371 : & rho_wrk(ipointlocal),&
372 : & nrec, rset%efermi,tsmear,rtrotter,dim_trott, &
373 : & rset%ZT_p, &
374 : & tolrec,dtset%typat,rset%nl,&
375 : & rset%mpi,nfftrec,ngfftrec,rset%inf,&
376 17280 : & tim_fourdp,dtset%natom,projec,1)
377 17280 : ipointlocal = ipointlocal + 1
378 : ! write(std_out,*)'ipointlocal',ipoint,ipointlocal,ii,jj,kk
379 17280 : call prtwork(dtset%recgratio**3*ipointlocal*100*rset%mpi%nproc/nfftrec)
380 18689 : if(ipoint==recpar%max_pt) exit graou1
381 : end do
382 : end do
383 : end do graou1
384 : else !--We use a troncation
385 21 : ABI_MALLOC(exppotloc,(0:nfftrec-1))
386 21 : graou2 : do kk = recpar%pt0%z,recpar%pt1%z,dtset%recgratio
387 84 : do jj = 0,n2-1,dtset%recgratio
388 259 : do ii = 0,n1-1,dtset%recgratio
389 189 : ipoint = ii+(jj+kk*n2)*n1
390 189 : if (ipoint<recpar%min_pt) cycle
391 : ! computation done by that proc
392 12285 : exppotloc = zero
393 : ! --Traslation to move position on the ngfftrec grid center
394 756 : trasl = -(/ii,jj,kk/)+ngfftrec(:3)/2
395 189 : if(rset%nl%nlpsp) then
396 0 : do iatom=1,dtset%natom
397 : ! --local position of atoms
398 0 : gcart_loc(:,iatom) = rset%inf%gcart(:,iatom)+trasl
399 0 : gcart_loc(:,iatom) = modulo(gcart_loc(:,iatom),(/n1,n2,n3/))
400 : ! --Traslation of non-local projectors
401 0 : do ilmn = 1,rset%nl%lmnmax
402 0 : projec(:,:,:,ilmn,iatom) = reshape(rset%nl%projec(:,ilmn,dtset%typat(iatom)),shape=shape(projec(:,:,:,1,1)))
403 0 : do ii1=1,3
404 0 : projec(:,:,:,ilmn,iatom) = eoshift(projec(:,:,:,ilmn,iatom),shift=ngfftrec(ii1)/2-gcart_loc(ii1,iatom),dim=ii1)
405 : end do
406 : end do
407 : end do
408 : end if
409 :
410 : call reshape_pot(trasl,nfftf,nfftrec,&
411 : & dtset%ngfft(:3),ngfftrec(:3),&
412 189 : & exppot,exppotloc)
413 :
414 189 : tim_fourdp=6
415 : call recursion(exppotloc,ngfftrec(1)/2,ngfftrec(2)/2,ngfftrec(3)/2, &
416 : & a_wrk(:,ipointlocal), &
417 : & b2_wrk(:,ipointlocal), &
418 : & rho_wrk(ipointlocal),&
419 : & nrec, rset%efermi,tsmear,rtrotter,dim_trott, &
420 : & rset%ZT_p, &
421 : & tolrec,dtset%typat,rset%nl,&
422 : & rset%mpi,nfftrec,ngfftrec,rset%inf,&
423 189 : & tim_fourdp,dtset%natom,projec,1)
424 189 : ipointlocal = ipointlocal + 1
425 189 : call prtwork(factor*real(ipointlocal,dp))
426 245 : if(ipoint==recpar%max_pt) exit graou2
427 : end do
428 : end do
429 : end do graou2
430 7 : ABI_FREE(exppotloc)
431 : end if
432 :
433 : end if
434 38 : write(msg,'( a12,i12)')'ipointlocal',ipointlocal
435 38 : call wrtout(std_out,msg,'PERS')
436 38 : call timab(613+swt_tm,1,tsec2) !!--start time-counter: sync gpu-cpu
437 38 : call xmpi_barrier(rset%mpi%comm_bandfft)
438 38 : call timab(613+swt_tm,2,tsec2) !!--stop time-counter: sync gpu-cpu
439 :
440 : !!#############################################################
441 : !!--ASSIGNATION PARAMETERS TO MENAGE PARALLELISME OF TRANSGRID
442 38 : if((rset%load==1 .or. dtset%recgratio>1))then
443 : ! --Bufsize contains the values of the number of points calculated
444 : ! by any proc on the coarse grid; bufsize_f on the fine grid
445 7 : call timab(604,1,tsec2) !--start time-counter: transgrid
446 21 : ABI_MALLOC(bufsize,(0:rset%mpi%nproc-1))
447 14 : ABI_MALLOC(bufdispl,(0:rset%mpi%nproc-1))
448 14 : bufsize = 0;
449 7 : bufsize(rset%mpi%me) = rset%par%npt
450 7 : call xmpi_sum(bufsize,rset%mpi%comm_bandfft,ierr)
451 :
452 7 : bufdispl(0) = 0;
453 7 : if(rset%mpi%nproc>1) bufdispl(1:) = (/(sum(bufsize(:ii)),ii=0,rset%mpi%nproc-1)/)
454 14 : call timab(604,2,tsec2) !--stop time-counter: transgrid
455 : end if
456 : !!####################################################################
457 : !!--REDISTRIBUTION OF LOAD ON PROCS AFTER RECURSION IF CUDA IS USED
458 : #ifdef HAVE_GPU_CUDA
459 : if(rset%load==1)then
460 : call timab(604,1,tsec2) !--start time-counter: transgrid
461 : call xredistribute(rho_hyb,rset%GPU%par%vcount,rset%GPU%par%displs,&
462 : & rholocal,bufsize,bufdispl,rset%mpi%me,&
463 : & rset%mpi%nproc,&
464 : & rset%mpi%comm_bandfft,ierr)
465 :
466 :
467 : ABI_MALLOC(vcount_0,(0:rset%mpi%nproc-1))
468 : ABI_MALLOC(displs_0,(0:rset%mpi%nproc-1))
469 : ABI_MALLOC(vcount_1,(0:rset%mpi%nproc-1))
470 : ABI_MALLOC(displs_1,(0:rset%mpi%nproc-1))
471 :
472 : vcount_0 = 0
473 : vcount_0(rset%mpi%me) = rset%par%npt*(nrec+1)
474 : call xmpi_sum(vcount_0,rset%mpi%comm_bandfft,ierr)
475 : displs_0 = 0
476 : if(rset%mpi%nproc>1) displs_0(1:) = (/(sum(vcount_0(:ii)),ii=0,rset%mpi%nproc-1)/)
477 :
478 :
479 : vcount_1 = 0
480 : vcount_1(rset%mpi%me) = rset%GPU%par%npt*(nrec+1)
481 : call xmpi_sum(vcount_1,rset%mpi%comm_bandfft,ierr)
482 : displs_1 = 0
483 : if(rset%mpi%nproc>1) displs_1(1:) = (/(sum(vcount_1(:ii)),ii=0,rset%mpi%nproc-1)/)
484 :
485 :
486 : call xredistribute(a_hyb,vcount_1,displs_1,&
487 : & alocal,vcount_0,displs_0,&
488 : & rset%mpi%me,rset%mpi%nproc,&
489 : & rset%mpi%comm_bandfft,ierr)
490 :
491 : call xredistribute(b2_hyb,vcount_1,displs_1,&
492 : & b2local,vcount_0,displs_0,&
493 : & rset%mpi%me,rset%mpi%nproc,&
494 : & rset%mpi%comm_bandfft,ierr)
495 :
496 : nullify(rho_wrk,a_wrk,b2_wrk)
497 : ABI_FREE(rho_hyb)
498 : ABI_FREE(a_hyb)
499 : ABI_FREE(b2_hyb)
500 : ABI_FREE(vcount_0)
501 : ABI_FREE(displs_0)
502 : ABI_FREE(vcount_1)
503 : ABI_FREE(displs_1)
504 : call timab(604,2,tsec2) !--start time-counter: transgrid
505 : end if
506 : #endif
507 :
508 : !#############################################################
509 : !--TRANSGRID FOR THE DENSITY RHO AND THE COEFFICIENTS AN AND B2N
510 38 : if (dtset%recgratio>1) then
511 : ! --variables allocation and initialisation-------
512 7 : write (msg,'(a)')' - TRANSGRID USING -----'
513 7 : call wrtout(std_out,msg,'COLL')
514 7 : call timab(604,1,tsec2) !--start time-counter: transgrid
515 :
516 21 : ABI_MALLOC(rholocal_f,(rset%pawfgr%nfft))
517 21 : ABI_MALLOC(rhogf,(2,rset%pawfgr%nfft))
518 21 : ABI_MALLOC(rhogc,(2,rset%pawfgr%nfftc))
519 21 : ABI_MALLOC(rholoc_2,(1:rset%pawfgr%nfftc))
520 35 : ABI_MALLOC(ablocal_2,(1:rset%pawfgr%nfftc,0:nrec,2))
521 35 : ABI_MALLOC(ablocal_f,(1:rset%pawfgr%nfft,0:nrec,2))
522 35 : ABI_MALLOC(ablocal_1,(1:rset%par%npt,0:nrec,2))
523 :
524 7 : call rset%mpi%distribfft%free()
525 7 : call rset%mpi%distribfft%init('c',rset%mpi%nproc_fft,rset%pawfgr%ngfftc(2) ,rset%pawfgr%ngfftc(3))
526 7 : call rset%mpi%distribfft%init('f',rset%mpi%nproc_fft,rset%pawfgr%ngfft(2) ,rset%pawfgr%ngfft(3))
527 :
528 338933 : rholocal_f = zero; ablocal_f = zero; ablocal_2 = zero
529 :
530 2611 : ablocal_1(:,:,1) = transpose(alocal(:,1:rset%par%npt))
531 2611 : ablocal_1(:,:,2) = transpose(b2local(:,1:rset%par%npt))
532 :
533 7 : if(get_K_S_G==1 .and. dtset%recgratio>1 ) then
534 8 : ABI_MALLOC(aloc_copy,(0:nrec,1:rset%par%npt))
535 6 : ABI_MALLOC(b2loc_copy,(0:nrec,1:rset%par%npt))
536 436 : aloc_copy = alocal(:,1:rset%par%npt)
537 436 : b2loc_copy = b2local(:,1:rset%par%npt)
538 : end if
539 :
540 7 : if(rset%mpi%nproc ==1) then
541 : ! --SEQUENTIAL CASE--
542 203 : rholoc_2 = rholocal(1:rset%par%npt)
543 5236 : ablocal_2 = ablocal_1
544 : ! --Transigrid: coarse->fine
545 36862 : rhogf = zero; rhogc = zero
546 7 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,rset%pawfgr,rhogc,rhogf,rholoc_2,rholocal_f)
547 21 : do jj1 = 1,2
548 207 : do ipoint = 0,nrec
549 979476 : rhogf = zero; rhogc = zero
550 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,rset%pawfgr,rhogc,rhogf,&
551 200 : & ablocal_2(:,ipoint,jj1),ablocal_f(:,ipoint,jj1))
552 : end do
553 : end do
554 : ! --Assignation of the interpolated results on the fine grid--
555 12103 : rholocal = rholocal_f
556 172807 : alocal = transpose(ablocal_f(:,:,1))
557 172807 : b2local = transpose(ablocal_f(:,:,2))
558 :
559 : else
560 : ! --PARALLEL CASE--
561 0 : rholoc_2 = zero
562 : ! --Send on all procs rho,an,bn--
563 : call xmpi_allgatherv(rholocal(1:rset%par%npt),bufsize(rset%mpi%me),rholoc_2,&
564 0 : & bufsize,bufdispl,rset%mpi%comm_bandfft,ierr)
565 0 : do irec = 0,nrec
566 : call xmpi_allgatherv(ablocal_1(1:rset%par%npt,irec,1),bufsize(rset%mpi%me),&
567 0 : & ablocal_2(:,irec,1),bufsize,bufdispl,rset%mpi%comm_bandfft,ierr)
568 : call xmpi_allgatherv(ablocal_1(1:rset%par%npt,irec,2),bufsize(rset%mpi%me),&
569 0 : & ablocal_2(:,irec,2),bufsize,bufdispl,rset%mpi%comm_bandfft,ierr)
570 : end do
571 :
572 :
573 : ! --Transigrid: coarse->fine on differents procs (with respect
574 : ! the number of recursion)
575 0 : rhogf = zero; rhogc = zero
576 0 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,rset%pawfgr,rhogc,rhogf,rholoc_2,rholocal_f)
577 :
578 0 : do irec = 0,2*(nrec+1)-1
579 0 : ii1 = modulo(irec,rset%mpi%nproc)
580 0 : jj1 = 1+modulo(irec,2)
581 0 : kk1 = floor(irec/2.)
582 0 : if(maxval(abs(ablocal_2(:,kk1,jj1))) > tol10 .and. rset%mpi%me == ii1) then
583 0 : rhogf = zero; rhogc = zero
584 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,rset%pawfgr,rhogc,&
585 0 : & rhogf,ablocal_2(:,kk1,jj1),ablocal_f(:,kk1,jj1))
586 : end if
587 : end do
588 :
589 : ! --Recuperation of all interpolated results
590 : ! from procs to allprocs
591 0 : call xmpi_sum(ablocal_f,rset%mpi%comm_bandfft,ierr)
592 :
593 : ! --Assignation the interpolated results on the fine grid
594 : ! any procs to obtain the same point as in the standard recursion
595 0 : do ii1 = 0, rset%mpi%nproc-1
596 0 : jj1 = rset%par%displs(ii1)+1
597 0 : if(ii1 == rset%mpi%me) then
598 0 : alocal = transpose(ablocal_f(jj1:jj1+rset%par%vcount(ii1)-1,:,1))
599 0 : b2local = transpose(ablocal_f(jj1:jj1+rset%par%vcount(ii1)-1,:,2))
600 0 : rholocal = rholocal_f(jj1:jj1+rset%par%vcount(ii1)-1)
601 : end if
602 : end do
603 : end if
604 7 : ABI_FREE(ablocal_f)
605 7 : ABI_FREE(ablocal_2)
606 7 : ABI_FREE(ablocal_1)
607 7 : ABI_FREE(rhogf)
608 7 : ABI_FREE(rholocal_f)
609 7 : ABI_FREE(rhogc)
610 7 : ABI_FREE(rholoc_2)
611 :
612 7 : call timab(604,2,tsec2) !--stop time-counter: transgrid
613 : else
614 31 : write(msg,'(a)')' - TRANSGRID NOT USED --'
615 31 : call wrtout(std_out,msg,'COLL')
616 : end if
617 : !!--End transgrid
618 : !!###############################################################
619 : !###################################
620 : !--Fermi energy computation
621 : !--find the good mu by imposing the electrons number
622 : call fermisolverec(rset%efermi,rholocal,alocal,b2local,rset%debug,&
623 : & rset%min_nrec,tsmear,trotter,nelect,tol10,100, &
624 : & rset%par%ntranche,rset%mpi,inf_ucvol,& !.False. .and.&
625 76 : & (rset%tp==2 .or. rset%tp==3) .and. trotter>1)
626 :
627 : !#################################################################
628 : !######### ENTROPY AND GRAN POTENTIAL COMPUTATION ##################
629 38 : entropy = zero
630 38 : gran_pot = zero
631 38 : noentropie : if(get_K_S_G==1)then
632 11 : entropy1 = zero; entropy2 = zero ;entropy3 = zero; entropy4 = zero
633 11 : gran_pot1 = zero ; gran_pot2 = zero; gran_pot3 = zero; gran_pot4 = zero
634 :
635 : ! --Seek for the min of the path integral
636 11 : potmin = zero; nlpotmin = zero
637 17301 : if(dtset%rectesteg/=1) potmin = minval(vtrial(:,1))
638 11 : if(rset%nl%nlpsp) nlpotmin = minval(rset%nl%eival(:,:,:))
639 11 : xmax = exp(-ratio2*(potmin+nlpotmin-rset%efermi))
640 :
641 11 : dim_entro = 0; if(rset%debug) dim_entro = 4;
642 :
643 11 : if(dtset%recgratio>1) then
644 : ! --Recgratio>1
645 6 : ABI_MALLOC(rhogf,(2,rset%pawfgr%nfft))
646 6 : ABI_MALLOC(rhogc,(2,rset%pawfgr%nfftc))
647 6 : ABI_MALLOC(entropy_v_f,(rset%pawfgr%nfft,0:4))
648 6 : ABI_MALLOC(entropy_v_c,(rset%pawfgr%nfftc,0:4))
649 6 : ABI_MALLOC(entropy_v_2,(1:rset%par%npt,0:4))
650 4 : ABI_MALLOC(gran_pot_v_f,(rset%pawfgr%nfft,0:4))
651 4 : ABI_MALLOC(gran_pot_v_c,(rset%pawfgr%nfftc,0:4))
652 4 : ABI_MALLOC(gran_pot_v_2,(1:rset%par%npt,0:4))
653 :
654 17852 : entropy_v_c = zero; entropy_v_f = zero; entropy_v_2 = zero
655 17852 : gran_pot_v_c = zero; gran_pot_v_f = zero; gran_pot_v_2 = zero
656 :
657 :
658 56 : do ipoint = 1,rset%par%npt
659 : call entropyrec(exp(rset%efermi*ratio2)*aloc_copy(:,ipoint), &
660 : & exp(rset%efermi*ratio1)*b2loc_copy(:,ipoint), &
661 : & nrec,trotter,entropy_v_2(ipoint,0),two,&
662 : & rset%debug,n_pt_integ_entropy,perc_vmin*xmax,&
663 : & entropy_v_2(ipoint,1),&
664 : & entropy_v_2(ipoint,2),&
665 : & entropy_v_2(ipoint,3),&
666 810 : & entropy_v_2(ipoint,4))
667 :
668 : call gran_potrec(exp(rset%efermi*ratio2)*aloc_copy(:,ipoint), &
669 : & exp(rset%efermi*ratio1)*b2loc_copy(:,ipoint), &
670 : & nrec,trotter,gran_pot_v_2(ipoint,0),two,&
671 : & rset%debug,n_pt_integ_entropy,perc_vmin*xmax,&
672 : & gran_pot_v_2(ipoint,1),&
673 : & gran_pot_v_2(ipoint,2),&
674 : & gran_pot_v_2(ipoint,3),&
675 812 : & gran_pot_v_2(ipoint,4))
676 : end do
677 2 : ABI_FREE(aloc_copy)
678 2 : ABI_FREE(b2loc_copy)
679 :
680 2 : call timab(613+swt_tm,1,tsec2) !!--start time-counter: sync gpu-cpu
681 2 : call xmpi_barrier(rset%mpi%comm_bandfft)
682 2 : call timab(613+swt_tm,2,tsec2) !!--stop time-counter: sync gpu-cpu
683 :
684 2 : call timab(604,1,tsec2) !--start time-counter: transgrid
685 2 : if(rset%mpi%nproc==1) then
686 284 : entropy_v_c = entropy_v_2
687 284 : gran_pot_v_c = gran_pot_v_2
688 : end if
689 4 : do ii1 = 0,dim_entro
690 : call xmpi_allgatherv(entropy_v_2(:,ii1),bufsize(rset%mpi%me),&
691 : & entropy_v_c(:,ii1),bufsize,bufdispl,&
692 2 : & rset%mpi%comm_bandfft,ierr)
693 : call xmpi_allgatherv(gran_pot_v_2(:,ii1),bufsize(rset%mpi%me),&
694 : & gran_pot_v_c(:,ii1),bufsize,bufdispl,&
695 2 : & rset%mpi%comm_bandfft,ierr)
696 :
697 58 : if(maxval(abs(entropy_v_c(:,ii1))) > tol10) then
698 10532 : rhogf = zero; rhogc = zero
699 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,&
700 2 : & rset%pawfgr,rhogc,rhogf,entropy_v_c(:,ii1),entropy_v_f(:,ii1))
701 : end if
702 60 : if(maxval(abs(gran_pot_v_c(:,ii1))) >tol10) then
703 10532 : rhogf = zero; rhogc = zero
704 : call transgrid(1,rset%mpi,dtset%nspden,1,0,0,1,&
705 2 : & rset%pawfgr,rhogc,rhogf,gran_pot_v_c(:,ii1),gran_pot_v_f(:,ii1))
706 : end if
707 : end do
708 2 : call timab(604,2,tsec2) !--stop time-counter: transgrid
709 :
710 3458 : entropy = sum(entropy_v_f(:,0))
711 3458 : gran_pot = sum(gran_pot_v_f(:,0))
712 :
713 2 : if(rset%debug)then
714 0 : entropy1 = sum(entropy_v_f(:,1))
715 0 : entropy2 = sum(entropy_v_f(:,2))
716 0 : entropy3 = sum(entropy_v_f(:,3))
717 0 : entropy4 = sum(entropy_v_f(:,4))
718 0 : gran_pot1 = sum(gran_pot_v_f(:,1))
719 0 : gran_pot2 = sum(gran_pot_v_f(:,2))
720 0 : gran_pot3 = sum(gran_pot_v_f(:,3))
721 0 : gran_pot4 = sum(gran_pot_v_f(:,4))
722 : end if
723 :
724 2 : ABI_FREE(entropy_v_f)
725 2 : ABI_FREE(entropy_v_c)
726 2 : ABI_FREE(entropy_v_2)
727 2 : ABI_FREE(rhogf)
728 2 : ABI_FREE(rhogc)
729 2 : ABI_FREE(gran_pot_v_f)
730 2 : ABI_FREE(gran_pot_v_c)
731 2 : ABI_FREE(gran_pot_v_2)
732 :
733 :
734 : else
735 : ! --Recgratio=1
736 5193 : do ipoint = 1,rset%par%ntranche
737 : call entropyrec(exp(rset%efermi*ratio2)*alocal(:,ipoint), &
738 : & exp(rset%efermi*ratio1)*b2local(:,ipoint), &
739 : & nrec,trotter,entropylocal,two,&
740 : & rset%debug,n_pt_integ_entropy,perc_vmin*xmax,&
741 : & entropylocal1,entropylocal2,&
742 77760 : & entropylocal3,entropylocal4)
743 : call gran_potrec(exp(rset%efermi*ratio2)*alocal(:,ipoint), &
744 : & exp(rset%efermi*ratio1)*b2local(:,ipoint), &
745 : & nrec,trotter,gran_pot_local,two,& !/ucvol,&
746 : & rset%debug,n_pt_integ_entropy,perc_vmin*xmax,&
747 : & gran_pot_local1,gran_pot_local2,&
748 77760 : & gran_pot_local3,gran_pot_local4)
749 :
750 5184 : entropy = entropy + entropylocal
751 5184 : gran_pot = gran_pot + gran_pot_local
752 5193 : if(rset%debug)then
753 0 : entropy1 = entropy1 + entropylocal1
754 0 : entropy2 = entropy2 + entropylocal2
755 0 : entropy3 = entropy3 + entropylocal3
756 0 : entropy4 = entropy4 + entropylocal4
757 0 : gran_pot1 = gran_pot1 + gran_pot_local1
758 0 : gran_pot2 = gran_pot2 + gran_pot_local2
759 0 : gran_pot3 = gran_pot3 + gran_pot_local3
760 0 : gran_pot4 = gran_pot4 + gran_pot_local4
761 : end if
762 :
763 : end do
764 :
765 9 : call xmpi_sum(entropy,rset%mpi%comm_bandfft ,ierr)
766 9 : call xmpi_sum(gran_pot,rset%mpi%comm_bandfft ,ierr)
767 9 : if(rset%debug)then
768 0 : call xmpi_sum(entropy1,rset%mpi%comm_bandfft ,ierr)
769 0 : call xmpi_sum(entropy2,rset%mpi%comm_bandfft ,ierr)
770 0 : call xmpi_sum(entropy3,rset%mpi%comm_bandfft ,ierr)
771 0 : call xmpi_sum(entropy4,rset%mpi%comm_bandfft ,ierr)
772 0 : call xmpi_sum(gran_pot1,rset%mpi%comm_bandfft ,ierr)
773 0 : call xmpi_sum(gran_pot2,rset%mpi%comm_bandfft ,ierr)
774 0 : call xmpi_sum(gran_pot3,rset%mpi%comm_bandfft ,ierr)
775 0 : call xmpi_sum(gran_pot4,rset%mpi%comm_bandfft ,ierr)
776 : end if
777 : end if
778 :
779 11 : if(rset%debug)then
780 : write(msg,'(2(2a,4(2a,es11.4,a)))')&
781 0 : & ' --------------------------' ,ch10, &
782 0 : & ' entropy, horiz path=',' ',entropy1,ch10, &
783 0 : & ' entropy, xmax path=',' ',entropy2,ch10, &
784 0 : & ' entropy, xmin path=',' ',entropy3,ch10, &
785 0 : & ' entropy, zero path=',' ',entropy4,ch10, &
786 0 : & ' --------------------------' ,ch10, &
787 0 : & ' -omega/T, horiz path=',' ',gran_pot1,ch10, &
788 0 : & ' -omega/T, xmax path=',' ',gran_pot2,ch10, &
789 0 : & ' -omega/T, xmin path=',' ',gran_pot3,ch10, &
790 0 : & ' -omega/T, zero path=',' ',gran_pot4,ch10
791 0 : call wrtout(std_out,msg,'COLL')
792 : end if
793 :
794 11 : e_eigenvalues=tsmear*(entropy-gran_pot) + rset%efermi*nelect
795 : ! --In reality gran_pot is not the gran potential but the
796 : ! potential omega=-PV (Landau-potential or grand-potential)
797 : ! divided by -T so the internal energy
798 : ! U:=e_eigenvalues= TS+omega+muN = ST-T*sum(ln(1-n))+muN =
799 : ! T(S-gran_pot)+muN
800 :
801 :
802 11 : if(rset%nl%nlpsp) then
803 : call nlenergyrec(rset,enlx,exppot,dtset%ngfft,dtset%natom,&
804 0 : & dtset%typat,tsmear,trotter,tolrec)
805 : end if
806 : end if noentropie
807 : !##### END ENTROPY AND GRAN POTENTIAL COMPUTATION ##################
808 : !#################################################################
809 :
810 : !if(associated(projec))
811 38 : if(rset%nl%nlpsp) then
812 0 : ABI_FREE(projec)
813 : end if
814 38 : if(associated(gcart_loc)) then
815 35 : ABI_FREE(gcart_loc)
816 : end if
817 38 : if((dtset%recgratio/=1 .or. rset%load==1)) then
818 7 : ABI_FREE(bufdispl)
819 7 : ABI_FREE(bufsize)
820 : end if
821 : !------------------------------------------------------------------
822 : !--Check if the convergence is reached for rho
823 29452 : drho = maxval(abs(rhor(min_pt:max_pt,1)-rholocal(:)))
824 : drhomax = drho
825 38 : call xmpi_max(drho,drhomax,rset%mpi%comm_bandfft,ierr)
826 :
827 : !write(std_out,*)'drhomax,toldrho',drhomax,toldrho
828 38 : if(drhomax<toldrho)then
829 22 : rset%quitrec = rset%quitrec+1
830 : else
831 16 : rset%quitrec = 0
832 : end if
833 :
834 : !-------------------------------------------------------------------
835 : !--Density on all procs
836 29414 : rhor(min_pt:max_pt,1) = rholocal(:)
837 38 : if(rset%mpi%nproc /= 1)then
838 : call xmpi_allgatherv(rholocal,rset%par%ntranche,rhor(:,1),&
839 : & rset%par%vcount,rset%par%displs,&
840 28 : & rset%mpi%comm_band,ierr)
841 : end if
842 :
843 : !--------------------------------------------------------------------
844 : !--2nd EKIN CALCULATION: this method is used
845 38 : noekin2 : if(get_K_S_G==1)then
846 8651 : intrhov = (inf_ucvol)*sum(rholocal*vtrial(min_pt:max_pt,1))
847 11 : call xmpi_sum(intrhov,rset%mpi%comm_bandfft ,ierr)
848 :
849 11 : ek = e_eigenvalues-intrhov-enlx
850 :
851 :
852 11 : if(rset%debug) then
853 0 : write (msg,'(2a,3f15.10,2a,3f15.10,2a,f15.10,a)') ch10,&
854 0 : & ' ek,int(rho*V),ek+int(rho*V) ', ek, intrhov, ek+ intrhov,ch10, &
855 0 : & ' kT*S, kT*sum(ln(...)), diff ', tsmear*entropy, tsmear*gran_pot, tsmear*(entropy-gran_pot),ch10, &
856 0 : & ' kT(S-sum(ln(...)))+mu*nelect', tsmear*(entropy-gran_pot)+rset%efermi*nelect,ch10
857 0 : call wrtout(std_out,msg,'COLL')
858 : end if
859 :
860 :
861 : end if noekin2
862 : !--------------------------------------------------------------------
863 38 : fermie = rset%efermi
864 :
865 : !--------------------------------------------------------
866 : !!--At the first step to find the max number of recursion
867 : !! needed to convergence, then redefine nrec.
868 38 : if(initialized==0 .and. dtset%ntime>0) then
869 6 : call Calcnrec(rset,b2local)
870 : end if
871 :
872 : !--------------------------------------------------------
873 38 : call rset%mpi%distribfft%free()
874 38 : call rset%mpi%distribfft%init('c',rset%mpi%nproc_fft,rset%ngfftrec(2),rset%ngfftrec(3))
875 38 : call rset%mpi%distribfft%init('f',rset%mpi%nproc_fft,dtset%ngfft(2),dtset%ngfft(3))
876 :
877 : !--Printing results
878 : write(msg,'(3a,f15.10)')&
879 38 : & ' -- Results: --------------------------------------',ch10,&
880 76 : & ' mu =',rset%efermi
881 38 : call wrtout(std_out,msg,'COLL')
882 38 : if(get_K_S_G==1)then
883 : write(msg,'(a,f15.10,6(2a,f15.10))')&
884 11 : & ' potmin =',potmin,ch10,&
885 11 : & ' <V_eff> =',intrhov,ch10,&
886 11 : & ' entropy =',entropy,ch10,&
887 11 : & ' -omega/T =',gran_pot,ch10,&
888 11 : & ' eigenvalues =',e_eigenvalues,ch10,&
889 11 : & ' kinetic =',ek,ch10,&
890 22 : & ' non-loc ene =',enlx
891 11 : call wrtout(std_out,msg,'COLL')
892 : end if
893 1938 : write(msg,'(a,50a)')' ',('-',ii=1,50)
894 38 : call wrtout(std_out,msg,'COLL')
895 : !write(std_out,*)'is the pressure ',gran_pot*tsmear/(rset%inf%ucvol*real(nfftrec,dp))
896 :
897 : !--Structured debugging : if rset%debug=T, stop here.
898 : if(.false.)then !(rset%debug)
899 : call wrtout(std_out,' rhor ','PERS')
900 : write(std_out,*)rhor(:,1)
901 : call wrtout(std_out,' ','COLL')
902 : write(msg,'(a,2d10.3)')' temps recursion ',tsec
903 : call wrtout(std_out,msg,'COLL')
904 : write(msg,'(a,l1,a)') ' vtorhorec : rset%debug=-',rset%debug,', debugging mode => stop '
905 : ABI_ERROR(msg)
906 : end if
907 :
908 38 : call timab(600,2,tsec2)
909 38 : call timab(21,2,tsec)
910 :
911 : call symrhg(1,gprimd,irrzon,rset%mpi,nfftf,&
912 : & dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%ngfft,dtset%nspden,&
913 38 : & dtset%nsppol,dtset%nsym,phnons,rhog,rhor,rprimd,dtset%symafm,dtset%symrel,dtset%tnons)
914 :
915 76 : end subroutine vtorhorec
916 : !!***
917 :
918 : !!****f* ABINIT/entropyrec
919 : !! NAME
920 : !! entropyrec
921 : !!
922 : !! FUNCTION
923 : !! This routine computes the local part of the entropy at a point using a path integral,
924 : !! in the recursion method.
925 : !!
926 : !! an, bn2 : coefficient given by the recursion.
927 : !! nrec=order of recursion
928 : !! trotter=trotter parameter
929 : !! multce=a multiplicator for computing entropy ; 2 for non-spin-polarized system
930 : !! debug_rec=debug variable
931 : !! n_pt_integ=number of points of integration for the path integral
932 : !! xmax =max point of integration on the real axis
933 :
934 : !! OUTPUT
935 : !! ent_out=entropy at the point
936 : !! ent_out1,ent_out2,ent_out3,ent_out4=debug entropy at the point
937 : !!
938 : !! NOTES
939 : !! at this time :
940 : !! - multce should be not used
941 : !! - the routine should be integraly rewrited and use the routine recursion.
942 : !! - only modified for p /= 0
943 : !!
944 : !! SOURCE
945 :
946 5238 : subroutine entropyrec(an,bn2,nrec,trotter,ent_out,multce,debug_rec, &
947 : & n_pt_integ,xmax,&
948 : & ent_out1,ent_out2,ent_out3,ent_out4)
949 :
950 : !Arguments -------------------------------
951 : !scalars
952 : integer,intent(in) :: n_pt_integ,nrec,trotter
953 : logical,intent(in) :: debug_rec
954 : real(dp), intent(in) :: multce,xmax
955 : real(dp),intent(out) :: ent_out,ent_out1,ent_out2,ent_out3,ent_out4
956 : !arrays
957 : real(dp),intent(in) :: an(0:nrec),bn2(0:nrec)
958 :
959 : !Local variables-------------------------------
960 : !scalars
961 : integer, parameter :: level = 7
962 : integer, save :: first_en = 1
963 : integer :: ii,kk,n_pt_integ_path2,n_pt_integ_path3
964 : real(dp) :: arg,epsilo,step,twotrotter,xmin,dr_step
965 : complex(dp) :: D,Dnew,Dold,N,Nnew,Nold,dz_path,ent_acc,ent_acc1,ent_acc2
966 : complex(dp) :: ent_acc3,ent_acc4
967 : complex(dp) :: funczero,z_path,zj
968 : complex(dp) ::delta_calc
969 : character(len=500) :: msg
970 : !arrays
971 : real(dp) :: tsec(2)
972 : real(dp) :: iif,factor
973 : ! *************************************************************************
974 :
975 5238 : call timab(610,1,tsec)
976 :
977 : !structured debugging if debug_rec=T : print detailled result the first time we enter entropyrec
978 :
979 5238 : if(debug_rec .and. first_en==1)then
980 0 : write(msg,'(a)')' '
981 0 : call wrtout(std_out,msg,'PERS')
982 0 : write(msg,'(a)')' entropyrec : enter '
983 0 : call wrtout(std_out,msg,'PERS')
984 0 : write(msg,'(a,i6)')'n_pt_integ ' , n_pt_integ
985 0 : call wrtout(std_out,msg,'COLL')
986 : end if
987 :
988 5238 : ent_out = zero
989 5238 : ent_out1 = zero
990 5238 : ent_out2 = zero
991 5238 : ent_out3 = zero
992 5238 : ent_out4 = zero
993 5238 : ent_acc = czero
994 5238 : ent_acc1 = czero
995 5238 : ent_acc2 = czero
996 5238 : ent_acc3 = czero
997 5238 : ent_acc4 = czero
998 :
999 : !path parameters
1000 5238 : twotrotter = max(two*real(trotter,dp),one)
1001 5238 : if(trotter==0)then
1002 : factor = tol5
1003 : arg =pi*three_quarters
1004 : zj = cmplx(-one,one-sin(arg),dp)
1005 : else
1006 5238 : factor = xmax/ten
1007 5238 : arg = pi/twotrotter
1008 5238 : zj = cmplx( cos(arg) , sin(arg),dp )
1009 : end if
1010 :
1011 5238 : epsilo = factor*sin( arg )
1012 5238 : xmin = factor*cos( arg )
1013 5238 : step = (xmax-xmin)/real(n_pt_integ,dp)
1014 :
1015 : !####################################################################
1016 : ![xmax + i*epsilo,xmin + i*epsilo]
1017 5238 : dr_step = one/real(n_pt_integ,dp)
1018 534276 : path1: do ii = 0,n_pt_integ
1019 529038 : z_path = cmplx(xmin+real(ii,dp)*(xmax-xmin)*dr_step,epsilo,dp)
1020 529038 : dz_path = -cmplx((xmax-xmin)*dr_step,zero,dp)
1021 :
1022 529038 : Nold = czero
1023 529038 : Dold = cone
1024 529038 : N = cone
1025 529038 : D = z_path - cmplx(an(0),zero,dp)
1026 :
1027 2116152 : do kk=1,nrec
1028 2116152 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1029 2116152 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1030 :
1031 2116152 : Nold = N
1032 2116152 : Dold = D
1033 2116152 : N = Nnew
1034 2116152 : D = Dnew
1035 :
1036 2645190 : if(kk/=nrec)then
1037 2116152 : if((bn2(kk+1)<tol14))exit
1038 : end if
1039 : end do
1040 :
1041 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1042 529038 : delta_calc = func1_rec(z_path**twotrotter)*(N/D)*dz_path
1043 534276 : if(ii==0.or.ii==n_pt_integ)then
1044 10476 : ent_acc = ent_acc + half*delta_calc
1045 10476 : ent_acc1 = ent_acc1 + half*delta_calc
1046 : else
1047 518562 : ent_acc = ent_acc + delta_calc
1048 518562 : ent_acc1 = ent_acc1 + delta_calc
1049 : end if
1050 : end do path1
1051 :
1052 :
1053 : !####################################################################
1054 : ![1/2zj,0]
1055 5238 : if(epsilo/step>100.d0)then
1056 0 : n_pt_integ_path2 = int((factor*abs(zj))/step)+1
1057 : else
1058 5238 : n_pt_integ_path2 = 100
1059 : end if
1060 :
1061 5238 : if(trotter/=0)then
1062 5238 : n_pt_integ_path3 = 0
1063 5238 : dr_step = one/real(n_pt_integ_path2,dp)
1064 5238 : dz_path = -cmplx(xmin,epsilo,dp)*dr_step
1065 534276 : path5: do ii = 0,n_pt_integ_path2
1066 529038 : z_path = cmplx(real(ii,dp)*xmin,real(ii,dp)*epsilo,dp)*dr_step
1067 534276 : if(abs(z_path)>tol14)then
1068 523800 : Nold = czero
1069 523800 : Dold = cone
1070 523800 : N = cone
1071 523800 : D = z_path - cmplx(an(0),zero,dp)
1072 2095200 : do kk=1,nrec
1073 2095200 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1074 2095200 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1075 2095200 : Nold = N
1076 2095200 : Dold = D
1077 2095200 : N = Nnew
1078 2095200 : D = Dnew
1079 2619000 : if(kk/=nrec)then
1080 2095200 : if((bn2(kk+1)<tol14))exit
1081 : end if
1082 : end do
1083 :
1084 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1085 523800 : if(abs(z_path)**twotrotter>tiny(one)) then
1086 523800 : funczero = func1_rec(z_path**twotrotter)
1087 : else
1088 : funczero = czero
1089 : end if
1090 523800 : delta_calc = funczero*N/D*dz_path
1091 523800 : if(ii==0.or.ii==n_pt_integ_path2)then
1092 5238 : ent_acc = ent_acc + half*delta_calc
1093 5238 : if(debug_rec) ent_acc3 = ent_acc3 + half*delta_calc
1094 : else
1095 518562 : ent_acc = ent_acc + funczero*delta_calc
1096 518562 : if(debug_rec) ent_acc3 = ent_acc3 + funczero*delta_calc
1097 : end if
1098 : end if
1099 : end do path5
1100 :
1101 : else ! trotter==0
1102 :
1103 0 : n_pt_integ_path3 = max(100,int((epsilo*half*pi)/real(step,dp))+1)
1104 0 : dr_step = one/real(n_pt_integ_path3,dp)
1105 0 : path6: do ii = 0,n_pt_integ_path3
1106 0 : iif=half*pi*real(ii,dp)*dr_step
1107 0 : z_path = epsilo*cmplx(-cos(iif),1-sin(iif),dp)
1108 0 : dz_path = epsilo*cmplx(sin(iif),-cos(iif),dp)*half*pi*dr_step
1109 0 : if(abs(z_path)**twotrotter>tol14)then
1110 0 : Nold = czero
1111 0 : Dold = cone
1112 0 : N = cone
1113 0 : D = z_path - cmplx(an(0),zero,dp)
1114 0 : do kk=1,nrec
1115 0 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1116 0 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1117 0 : Nold = N
1118 0 : Dold = D
1119 0 : N = Nnew
1120 0 : D = Dnew
1121 0 : if(kk/=nrec .and. bn2(kk+1)<tol14) exit !-EXIT
1122 : end do
1123 :
1124 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1125 0 : delta_calc = func1_rec(z_path**twotrotter) * N/D * dz_path
1126 0 : if(ii==0.or.ii==n_pt_integ_path3)then
1127 0 : ent_acc = ent_acc + half*delta_calc
1128 0 : if(debug_rec) ent_acc3 = ent_acc3 + half*delta_calc
1129 : else
1130 0 : ent_acc = ent_acc + delta_calc !<r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1131 0 : if(debug_rec) ent_acc3 = ent_acc3 + delta_calc !<r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1132 : end if
1133 : end if
1134 : end do path6
1135 :
1136 : end if
1137 :
1138 5238 : if(first_en==1 .and. debug_rec) then
1139 : write(msg,'(a,i5,2a,i5,2a,i5,2a,es11.4,2a,es11.4,2a,es11.4)')&
1140 0 : & 'n_pt_path =',n_pt_integ,ch10,&
1141 0 : & 'n_pt_path2 =',n_pt_integ_path2,ch10,&
1142 0 : & 'n_pt_path3 =',n_pt_integ_path3,ch10,&
1143 0 : & 'xmin =',xmin,ch10,&
1144 0 : & 'xmax =',xmax,ch10,&
1145 0 : & 'epsilon =',epsilo
1146 0 : call wrtout(std_out,msg,'COLL')
1147 0 : first_en = 0
1148 : end if
1149 :
1150 : !####################################################################
1151 : ![xmax,xmax+i*epsilo]
1152 5238 : dr_step = one/real(n_pt_integ_path2,dp)
1153 5238 : dz_path = cmplx(zero,epsilo*dr_step,dp)
1154 534276 : path4: do ii = 0,n_pt_integ_path2
1155 529038 : z_path = cmplx(xmax,real(ii,dp)*epsilo*dr_step,dp)
1156 :
1157 529038 : Nold = czero
1158 529038 : Dold = cone
1159 529038 : N = cone
1160 529038 : D = z_path - cmplx(an(0),zero,dp)
1161 :
1162 2116152 : do kk=1,nrec
1163 2116152 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1164 2116152 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1165 :
1166 2116152 : Nold = N
1167 2116152 : Dold = D
1168 2116152 : N = Nnew
1169 2116152 : D = Dnew
1170 :
1171 2645190 : if(kk/=nrec)then
1172 2116152 : if((bn2(kk+1)<tol14))exit
1173 : end if
1174 : end do
1175 :
1176 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1177 529038 : delta_calc = func1_rec(z_path**twotrotter)*N/D*dz_path
1178 534276 : if(ii==0.or.ii==n_pt_integ_path2)then
1179 :
1180 10476 : ent_acc = ent_acc + half*delta_calc
1181 10476 : if(debug_rec) ent_acc2 = ent_acc2 + half*delta_calc
1182 : else
1183 518562 : ent_acc = ent_acc + delta_calc
1184 518562 : if(debug_rec) ent_acc2 = ent_acc2 + delta_calc
1185 : end if
1186 : end do path4
1187 :
1188 :
1189 5238 : ent_out = multce*real(ent_acc*cmplx(zero,-piinv,dp),dp)
1190 5238 : if(debug_rec) then
1191 0 : ent_out1 = multce*real(ent_acc1*cmplx(zero,-piinv,dp),dp)
1192 0 : ent_out2 = multce*real(ent_acc2*cmplx(zero,-piinv,dp),dp)
1193 0 : ent_out3 = multce*real(ent_acc3*cmplx(zero,-piinv,dp),dp)
1194 0 : ent_out4 = multce*real(ent_acc4*cmplx(zero,-piinv,dp),dp)
1195 : end if
1196 :
1197 5238 : call timab(610,2,tsec)
1198 :
1199 : contains
1200 :
1201 : !function to integrate over the path
1202 : !func1_rec(z_path,twotrotter) = ( z_path**twotrotter/(1+z_path**twotrotter)*log(1+1/z_path**twotrotter)+& !- f*ln(f)
1203 : !&1/(1+z_path**twotrotter)*log(1+z_path**twotrotter)) !- (1-f)*ln(1-f)
1204 :
1205 : !func1_rec(z_path_pow) = z_path_pow/(cone+z_path_pow)*log(cone+cone/z_path_pow)+& !- f*ln(f)
1206 : !&cone/(cone+z_path_pow)*log(cone+z_path_pow) !- (1-f)*ln(1-f)
1207 :
1208 : !other expression of func for a path like ro(t)*exp(2*i*pi/(2*p)*(j+1/2))
1209 :
1210 1581876 : function func1_rec(z)
1211 :
1212 : complex(dp) :: func1_rec
1213 : complex(dp),intent(in) :: z
1214 :
1215 1581876 : func1_rec = z/(cone+z)*log(cone+cone/z)+ cone/(cone+z)*log(cone+z)
1216 :
1217 1581876 : end function func1_rec
1218 :
1219 : end subroutine entropyrec
1220 : !!***
1221 :
1222 : !!****f* ABINIT/fermisolverec
1223 : !! NAME
1224 : !! fermisolverec
1225 : !!
1226 : !! FUNCTION
1227 : !! This routine computes the fermi energy in order to have a given number of
1228 : !! valence electrons in the recursion method, using a Ridder s Method
1229 : !!
1230 : !! INPUTS
1231 : !! debug_rec=debugging variable
1232 : !! nb_rec=order of recursion
1233 : !! nb_point=number of discretization point in one dimension (=n1=n2=n3)
1234 : !! temperature=temperature (Hartree)
1235 : !! trotter=trotter parameter
1236 : !! nelect=number of valence electrons (dtset%nelect)
1237 : !! acc=accuracy for the fermi energy
1238 : !! max_it=maximum number of iteration for the Ridder's Method
1239 : !! long_tranche=number of point computed by thi proc
1240 : !! mpi_enreg=information about MPI parallelization
1241 : !! inf_ucvol=infinitesimal unit cell volume
1242 : !! gputopo=true if topology gpu-cpu= 2 or 3
1243 : !!
1244 : !! OUTPUT
1245 : !!
1246 : !! SIDE EFFECTS
1247 : !! fermie=fermi energy
1248 : !! rho=density, recomputed for the new fermi energy
1249 : !! a, b2 : coefficient given by recursion recomputed for the new fermi energy
1250 : !!
1251 : !! NOTES
1252 : !! at this time :
1253 : !!
1254 : !! SOURCE
1255 :
1256 38 : subroutine fermisolverec(fermie,rho,a,b2,debug_rec,nb_rec, &
1257 : & temperature,trotter,nelect, &
1258 : & acc, max_it, &
1259 : & long_tranche,mpi_enreg,&
1260 : & inf_ucvol,gputopo)
1261 :
1262 : !Arguments -------------------------------
1263 : !scalars
1264 : integer,intent(in) :: long_tranche,max_it,nb_rec,trotter
1265 : logical,intent(in) :: debug_rec,gputopo
1266 : real(dp),intent(in) :: acc,inf_ucvol,nelect,temperature
1267 : real(dp), intent(inout) :: fermie
1268 : type(MPI_type),intent(in) :: mpi_enreg
1269 : !arrays
1270 : real(dp), intent(inout) :: a(0:nb_rec,long_tranche), b2(0:nb_rec,long_tranche)
1271 : real(dp), intent(inout) :: rho(long_tranche)
1272 :
1273 : !Local variables-------------------------------
1274 : !scalars
1275 : integer :: ierr,ii,ipointlocal,nn,dim_trott
1276 : real(dp) :: beta,fermieh,fermiel,fermiem,fermienew,nelecth,nelectl,nelectm
1277 : real(dp) :: nelectnew,res_nelecth,res_nelectl,res_nelectm,res_nelectnew
1278 : real(dp) :: rtrotter,ss,fermitol
1279 : character(len=500) :: msg
1280 : !arrays
1281 : real(dp) :: tsec(2)
1282 76 : real(dp) :: rhotry(long_tranche)
1283 : !no_abirules
1284 : #ifdef HAVE_GPU_CUDA
1285 : integer :: swt_tm,npitch
1286 : real(cudap) :: rhocu(long_tranche)
1287 : real(dp) :: tsec2(2)
1288 : #endif
1289 :
1290 : ! *************************************************************************
1291 :
1292 : #ifdef HAVE_GPU_CUDA
1293 : swt_tm = 0
1294 : #endif
1295 :
1296 38 : call timab(609,1,tsec)
1297 :
1298 38 : beta = one/temperature
1299 38 : rtrotter = max(half,real(trotter,dp))
1300 38 : dim_trott = max(0,2*trotter-1)
1301 :
1302 38 : write(msg,'(a)')' -- fermisolverec ---------------------------------'
1303 38 : call wrtout(std_out,msg,'COLL')
1304 38 : if(debug_rec) then
1305 0 : write (msg,'(a,d10.3)')' nelect= ',nelect
1306 0 : call wrtout(std_out,msg,'COLL')
1307 : end if
1308 : !initialisation of fermiel
1309 38 : fermiel = fermie
1310 38 : call timab(609,2,tsec)
1311 :
1312 : !initialisation fermitol
1313 38 : fermitol = acc
1314 : #ifdef HAVE_GPU_CUDA_SP
1315 : if(gputopo) fermitol = 1.d-3
1316 : #endif
1317 :
1318 38 : if(gputopo) then
1319 : #ifdef HAVE_GPU_CUDA
1320 : swt_tm = 1
1321 : ! allocate array an and bn2 on gpu for computation of trotter formula
1322 : call alloc_dens_cuda(long_tranche,nb_rec,dim_trott,npitch,&
1323 : & real(a,cudap),real(b2,cudap))
1324 :
1325 : call timab(617,1,tsec)
1326 : call density_cuda(npitch,long_tranche,nb_rec,dim_trott,&
1327 : & real(fermiel,cudap),real(temperature,cudap),&
1328 : & real(rtrotter,cudap),real(inf_ucvol,cudap),&
1329 : & real(tol14,cudap),&
1330 : & rhocu)
1331 : rhotry = real(rhocu,dp)
1332 : call timab(617,2,tsec)
1333 : #endif
1334 : else
1335 29414 : do ipointlocal = 1,long_tranche
1336 : call density_rec(a(:,ipointlocal),&
1337 : & b2(:,ipointlocal),&
1338 : & rhotry(ipointlocal),&
1339 : & nb_rec,fermiel,temperature,rtrotter,dim_trott, &
1340 29414 : & tol14,inf_ucvol)
1341 : end do
1342 : end if
1343 :
1344 38 : call timab(609,1,tsec)
1345 29414 : nelectl = sum(rhotry)
1346 38 : call xmpi_sum( nelectl,mpi_enreg%comm_bandfft,ierr)
1347 38 : res_nelectl = inf_ucvol*nelectl - nelect
1348 :
1349 38 : if (res_nelectl /= zero) then
1350 : ! initialisation of fermih
1351 : ! excess of electrons -> smaller fermi
1352 38 : res_nelecth = zero
1353 38 : ii = 1
1354 38 : fermieh = fermie - ten*sign(one,res_nelectl)*temperature
1355 76 : do while(ii<6 .and. res_nelecth*res_nelectl>=0)
1356 38 : fermieh = fermieh - ten*sign(one,res_nelectl)*temperature
1357 38 : call timab(609,2,tsec)
1358 :
1359 38 : if(gputopo) then
1360 : #ifdef HAVE_GPU_CUDA
1361 : call timab(617,1,tsec)
1362 : call density_cuda(npitch,long_tranche,nb_rec,dim_trott,&
1363 : & real(fermieh,cudap),real(temperature,cudap),&
1364 : & real(rtrotter,cudap),real(inf_ucvol,cudap),&
1365 : & real(tol14,cudap),&
1366 : & rhocu)
1367 : rhotry = real(rhocu,dp)
1368 : call timab(617,2,tsec)
1369 : #endif
1370 : else
1371 29414 : do ipointlocal = 1,long_tranche
1372 : call density_rec(a(:,ipointlocal), &
1373 : & b2(:,ipointlocal), &
1374 : & rhotry(ipointlocal), &
1375 : & nb_rec,fermieh,temperature,rtrotter,dim_trott, &
1376 29414 : & tol14,inf_ucvol)
1377 : end do
1378 : end if
1379 38 : call timab(609,1,tsec)
1380 29414 : nelecth = sum(rhotry)
1381 38 : call xmpi_sum( nelecth,mpi_enreg%comm_bandfft ,ierr);
1382 38 : res_nelecth = inf_ucvol*nelecth - nelect
1383 :
1384 38 : if(debug_rec) then
1385 0 : write (msg,'(a,es11.4e2,a,es11.4e2)') ' Fermi energy interval',fermieh,' ',fermiel
1386 0 : call wrtout(std_out,msg,'COLL')
1387 : end if
1388 76 : ii = ii +1
1389 : end do
1390 :
1391 38 : if (res_nelecth*res_nelectl>0) then
1392 0 : write (msg,'(4a)')' fermisolverec : ERROR- ',ch10,&
1393 0 : & ' initial guess for fermi energy doesnt permit to find solutions in solver',ch10
1394 0 : ABI_ERROR(msg)
1395 : end if
1396 :
1397 : ! MAIN LOOP ------------------------------------------------------
1398 143 : main : do nn=1,max_it
1399 : ! fermiem computation
1400 143 : fermiem = 0.5d0*(fermiel+fermieh)
1401 :
1402 : ! nelectm = zero
1403 143 : call timab(609,2,tsec)
1404 :
1405 143 : if(gputopo) then
1406 : #ifdef HAVE_GPU_CUDA
1407 : call timab(617,1,tsec)
1408 : call density_cuda(npitch,long_tranche,nb_rec,dim_trott,&
1409 : & real(fermiem,cudap),real(temperature,cudap),&
1410 : & real(rtrotter,cudap),real(inf_ucvol,cudap),&
1411 : & real(tol14,cudap),&
1412 : & rhocu)
1413 : rhotry = real(rhocu,dp)
1414 : call timab(617,2,tsec)
1415 : #endif
1416 : else
1417 112463 : do ipointlocal = 1,long_tranche
1418 : call density_rec(a(:,ipointlocal), &
1419 : & b2(:,ipointlocal), &
1420 : & rhotry(ipointlocal), &
1421 : & nb_rec,fermiem,temperature,rtrotter,dim_trott, &
1422 112463 : & tol14,inf_ucvol)
1423 : end do
1424 : end if
1425 :
1426 143 : call timab(609,1,tsec)
1427 112463 : nelectm = sum(rhotry)
1428 143 : call xmpi_sum( nelectm,mpi_enreg%comm_bandfft,ierr)
1429 143 : res_nelectm = inf_ucvol*nelectm - nelect
1430 :
1431 : ! new guess
1432 143 : ss = sqrt(res_nelectm**two-res_nelectl*res_nelecth)
1433 143 : fermienew = fermiem + (fermiem-fermiel)*sign(one, res_nelectl-res_nelecth)*res_nelectm/ss
1434 :
1435 143 : call timab(609,2,tsec)
1436 143 : if(gputopo) then
1437 : #ifdef HAVE_GPU_CUDA
1438 : call timab(617,1,tsec)
1439 : call density_cuda(npitch,long_tranche,nb_rec,dim_trott,&
1440 : & real(fermienew,cudap),real(temperature,cudap),&
1441 : & real(rtrotter,cudap),real(inf_ucvol,cudap),&
1442 : & real(tol14,cudap),&
1443 : & rhocu)
1444 : rhotry = real(rhocu,dp)
1445 : call timab(617,2,tsec)
1446 : #endif
1447 : else
1448 112463 : do ipointlocal = 1,long_tranche
1449 : call density_rec(a(:,ipointlocal), &
1450 : & b2(:,ipointlocal), &
1451 : & rhotry(ipointlocal), &
1452 : & nb_rec,fermienew,temperature,rtrotter,dim_trott, &
1453 112463 : & tol14,inf_ucvol)
1454 : end do
1455 : end if
1456 :
1457 143 : call timab(609,1,tsec)
1458 112463 : nelectnew = sum(rhotry)
1459 143 : call xmpi_sum( nelectnew,mpi_enreg%comm_bandfft ,ierr);
1460 143 : res_nelectnew = inf_ucvol*nelectnew - nelect
1461 :
1462 : ! fermiel et fermieh for new iteration
1463 143 : if (sign(res_nelectm,res_nelectnew) /= res_nelectm) then
1464 30 : fermiel = fermiem
1465 30 : res_nelectl = res_nelectm
1466 30 : fermieh = fermienew
1467 30 : res_nelecth = res_nelectnew
1468 113 : else if (sign(res_nelectl,res_nelectnew) /= res_nelectl) then
1469 74 : fermieh = fermienew
1470 74 : res_nelecth = res_nelectnew
1471 39 : else if (sign(res_nelecth,res_nelectnew) /= res_nelecth) then
1472 39 : fermiel = fermienew
1473 39 : res_nelectl = res_nelectnew
1474 : end if
1475 :
1476 : ! are we within the tolerance ?
1477 429 : if ((abs(res_nelectnew) < fermitol).or.(nn == max_it)) then
1478 38 : fermie = fermienew
1479 29414 : rho = rhotry
1480 38 : if(debug_rec) then
1481 0 : write (msg,'(a,es11.4e2,a,i4)')' err, num_iter ', res_nelectnew, ' ',nn
1482 0 : call wrtout(std_out,msg,'COLL')
1483 0 : write(msg,'(a,50a)')' ',('-',ii=1,50)
1484 0 : call wrtout(std_out,msg,'COLL')
1485 : end if
1486 : exit main
1487 : end if
1488 :
1489 : end do main
1490 :
1491 : end if
1492 :
1493 : #ifdef HAVE_GPU_CUDA
1494 : !deallocate array on GPU
1495 : if(gputopo) then
1496 : call dealloc_dens_cuda()
1497 : end if
1498 : call timab(613+swt_tm,1,tsec2) !!--start time-counter: sync gpu-cpu
1499 : call xmpi_barrier(mpi_enreg%comm_bandfft)
1500 : call timab(613+swt_tm,2,tsec2) !!--stop time-counter: sync gpu-cpu
1501 : #endif
1502 :
1503 38 : call timab(609,2,tsec)
1504 38 : end subroutine fermisolverec
1505 : !!***
1506 :
1507 : !!****f* ABINIT/density_rec
1508 : !! NAME
1509 : !! density_rec
1510 : !!
1511 : !! FUNCTION
1512 : !! This routine computes the density using the coefficients corresponding to
1513 : !! continued fraction at a point from a fixed potential.
1514 : !!
1515 : !! INPUTS
1516 : !! coordx, coordy, coordz=coordonnees of the computed point
1517 : !! an, bn2 : coefficient given by density_rec. Input if get_rec_coef=0, output else
1518 : !! nrec=order of density_rec
1519 : !! fermie=fermi energy (Hartree)
1520 : !! tsmear=temperature (Hartree)
1521 : !! rtrotter=real trotter parameter
1522 : !! tol=tolerance criteria for stopping density_rec
1523 : !! inf_ucvol=infinitesimal unit cell volume
1524 : !! dim_trott = max(0,2*trotter-1)
1525 : !!
1526 : !! OUTPUT
1527 : !! rho_out=result of the continued fraction multiplied by a multiplicator
1528 : !!
1529 : !! SIDE EFFECTS
1530 : !!
1531 : !! NOTES
1532 : !! at this time :
1533 : !! - exppot should be replaced by ?
1534 : !! - coord should be replaced by ?
1535 : !! - need a rectangular box (rmet diagonal matrix)
1536 : !!
1537 : !! SOURCE
1538 :
1539 283392 : subroutine density_rec(an,bn2,rho_out,nrec, &
1540 : & fermie,tsmear,rtrotter, &
1541 : & dim_trott,tol,inf_ucvol)
1542 :
1543 : !Arguments -------------------------------
1544 : !scalars
1545 : integer,intent(in) :: nrec
1546 : integer,intent(in) :: dim_trott
1547 : real(dp),intent(in) :: fermie,tol,tsmear,inf_ucvol,rtrotter
1548 : real(dp), intent(out) :: rho_out
1549 : !arrays
1550 : real(dp),intent(in) :: an(0:nrec),bn2(0:nrec)
1551 : !Local variables-------------------------------
1552 : !not used, debugging purpose only
1553 : !for debugging purpose, detailled printing only once for density and ekin
1554 : !scalars
1555 : integer, parameter :: minrec = 3
1556 : integer :: irec
1557 : real(dp) :: beta,mult,prod_b2,error,errold
1558 : real(dp) :: pi_on_rtrotter,twortrotter,exp1,exp2
1559 : complex(dp) :: cinv2rtrotter,coeef_mu,facrec0
1560 : ! character(len=500) :: msg
1561 : !arrays
1562 : real(dp) :: tsec(2)
1563 566784 : complex(dp) :: acc_rho(0:nrec)
1564 566784 : complex(dp) :: D(0:dim_trott),Dold(0:dim_trott)
1565 566784 : complex(dp) :: N(0:dim_trott),Nold(0:dim_trott)
1566 : !**************************************************************************
1567 :
1568 283392 : call timab(605,1,tsec)
1569 :
1570 : !##############################################################
1571 : !--Initialisation of metrics
1572 283392 : mult = two/inf_ucvol !non-spined system
1573 283392 : beta = one/tsmear
1574 :
1575 : !--Variables for optimisation
1576 283392 : pi_on_rtrotter = pi/rtrotter
1577 283392 : twortrotter = two*rtrotter
1578 283392 : exp1 = exp((beta*fermie)/(rtrotter))
1579 283392 : exp2 = exp(beta*fermie/(twortrotter))
1580 283392 : cinv2rtrotter = cmplx(one/twortrotter,zero,dp)
1581 283392 : coeef_mu = cmplx(one/exp2,zero,dp)
1582 :
1583 11619072 : N = czero; D = cone
1584 283392 : facrec0 = cone
1585 11619072 : Nold = czero; Dold = czero
1586 : !--Initialisation of accumulated density
1587 5460480 : acc_rho = czero
1588 : !--Initialisation of estimated error
1589 283392 : prod_b2 = twortrotter/exp1
1590 283392 : errold = zero
1591 :
1592 :
1593 : !##############################################################
1594 : !--Main loop
1595 1353567 : maindo : do irec = 0, nrec
1596 :
1597 : ! ######################################################
1598 : ! --Density computation
1599 : ! !--using the property that: sum_i(bi*c)^2|(z-ai*c)=1/c*sum_i(bi)^2|(z/c-ai)
1600 : ! !and for c =exp(-beta*fermie/(two*rtrotter)
1601 :
1602 : call trottersum(dim_trott,error,prod_b2,pi_on_rtrotter,&
1603 : & facrec0,coeef_mu,exp1,&
1604 : & an(irec),bn2(irec),&
1605 1353567 : & N,D,Nold,Dold)
1606 :
1607 1353567 : if(irec/=nrec .and. irec>=minrec)then
1608 503391 : if((bn2(irec+1)<tol14).or.(mult*error<tol.and.errold<tol)) exit maindo
1609 : end if
1610 1353567 : errold = mult*error
1611 : end do maindo
1612 : !--Accumulated density
1613 5951232 : rho_out = mult*real(cone-sum(N/D)*cinv2rtrotter,dp)
1614 :
1615 283392 : call timab(605,2,tsec)
1616 :
1617 283392 : end subroutine density_rec
1618 : !!***
1619 :
1620 : !!****f* ABINIT/gran_potrec
1621 : !! NAME
1622 : !! gran_potrec
1623 : !!
1624 : !! FUNCTION
1625 : !! This routine computes the local part of the grand-potential at a point using a path integral,
1626 : !! in the recursion method.
1627 : !!
1628 : !! INPUTS
1629 : !! an, bn2 : coefficient given by the recursion.
1630 : !! nrec=order of recursion
1631 : !! trotter=trotter parameter
1632 : !! mult=a multiplicator for computing grand-potential (2 for non-spin-polarized system)
1633 : !! debug_rec=debugging variable
1634 : !! n_pt_integ=points for computation of path integral
1635 : !! xmax= maximum point on the x-axis for integration
1636 : !!
1637 : !! OUTPUT
1638 : !! ene_out=grand-potential at the point
1639 : !! if debug_rec=T then ene_out1,ene_out2,ene_out3,ene_out4 are
1640 : !! the different path branch contriubutions to the grand-potential.
1641 : !! In reality it is not the gren potential but the
1642 : !! grand-potential (omega=-PV) divided by -T
1643 : !!
1644 : !! NOTES
1645 : !! in reality it is not the gren potential but the grand-potential (omega=-PV) divided by -T
1646 : !! at this time :
1647 : !! - mult should be not used
1648 : !! - the routine should be integraly rewrited and use the routine recursion.
1649 : !! - only modified for p /= 0
1650 : !!
1651 : !! SOURCE
1652 :
1653 5238 : subroutine gran_potrec(an,bn2,nrec,trotter,ene_out, mult, &
1654 : & debug_rec,n_pt_integ,xmax,&
1655 : & ene_out1,ene_out2,ene_out3,ene_out4)
1656 :
1657 : !Arguments -------------------------------
1658 : !scalars
1659 : integer,intent(in) :: n_pt_integ,nrec,trotter
1660 : logical,intent(in) :: debug_rec
1661 : real(dp), intent(in) :: mult,xmax
1662 : real(dp),intent(inout) :: ene_out,ene_out1,ene_out2,ene_out3,ene_out4 !vz_i
1663 : !arrays
1664 : real(dp), intent(in) :: an(0:nrec),bn2(0:nrec)
1665 :
1666 : !Local variables-------------------------------
1667 : !scalars
1668 : integer, parameter :: level = 7
1669 : integer, save :: first = 1
1670 : integer :: ii,kk,n_pt_integ_path2
1671 : real(dp) :: epsilon,step,twotrotter,xmin,dr_step
1672 : complex(dp) :: D,Dnew,Dold,N,Nnew,Nold,dz_path,ene_acc,ene_acc1,ene_acc2
1673 : complex(dp) :: ene_acc3,ene_acc4
1674 : complex(dp) :: z_path,delta_calc
1675 : character(len=500) :: message
1676 : !arrays
1677 : real(dp) :: tsec(2)
1678 : ! *************************************************************************
1679 :
1680 :
1681 5238 : call timab(611,1,tsec)
1682 :
1683 : !structured debugging if debug_rec=T : print detailled result the first time we enter gran_potrec
1684 5238 : if(debug_rec .and. first==1)then
1685 0 : write(message,'(a)')' '
1686 0 : call wrtout(std_out,message,'PERS')
1687 0 : write(message,'(a)')' gran_potrec : enter '
1688 0 : call wrtout(std_out,message,'PERS')
1689 0 : write(message,'(a,i8)')'n_pt_integ ' , n_pt_integ
1690 0 : call wrtout(std_out,message,'COLL')
1691 0 : first=0
1692 : end if
1693 :
1694 5238 : ene_out = zero
1695 5238 : ene_acc = czero
1696 5238 : ene_acc1 = czero
1697 5238 : ene_acc2 = czero
1698 5238 : ene_acc3 = czero
1699 5238 : ene_acc4 = czero
1700 :
1701 :
1702 : !path parameters
1703 : !n_pt_integ = 2500
1704 5238 : xmin = -half
1705 5238 : step = (xmax-xmin)/real(n_pt_integ,dp)
1706 5238 : if(trotter==0)then
1707 0 : twotrotter = one
1708 0 : epsilon = .5d-1
1709 : else
1710 5238 : twotrotter = two*real(trotter,dp)
1711 5238 : epsilon = half*sin( pi/twotrotter)
1712 : end if
1713 :
1714 : !xmin = -abs(xmin)**(1.d0/twotrotter)
1715 :
1716 : !####################################################################
1717 : ![xmax + i*epsilon,xmin + i*epsilon]
1718 5238 : dr_step = one/real(n_pt_integ,dp)
1719 5238 : dz_path = -cmplx((xmax-xmin)*dr_step,zero,dp)
1720 534276 : path1: do ii = 0,n_pt_integ
1721 : ! z_path = cmplx(xmin + real(ii,dp)*(xmax-xmin)*dr_step,epsilon,dp)
1722 529038 : z_path = cmplx(xmin,epsilon,dp) - real(ii,dp)*dz_path
1723 529038 : Nold = czero
1724 529038 : Dold = cone
1725 529038 : N = cone
1726 529038 : D = z_path - cmplx(an(0),zero,dp)
1727 :
1728 2116152 : do kk=1,nrec
1729 2116152 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1730 2116152 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1731 :
1732 2116152 : Nold = N
1733 2116152 : Dold = D
1734 2116152 : N = Nnew
1735 2116152 : D = Dnew
1736 :
1737 2645190 : if(kk/=nrec)then
1738 2116152 : if((bn2(kk+1)<tol14))exit
1739 : end if
1740 :
1741 : end do
1742 :
1743 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1744 529038 : delta_calc = func_rec(z_path,twotrotter)* N/D *dz_path
1745 534276 : if(ii==0.or.ii==n_pt_integ)then
1746 10476 : ene_acc = ene_acc + half*delta_calc
1747 10476 : if(debug_rec) ene_acc1 = ene_acc1 + half*delta_calc
1748 : else
1749 518562 : ene_acc = ene_acc + delta_calc
1750 518562 : if(debug_rec) ene_acc1 = ene_acc1 + delta_calc
1751 : end if
1752 : end do path1
1753 :
1754 : !####################################################################
1755 : ![xmin + i*epsilon,xmin]
1756 5238 : if(epsilon/step>4.d0)then
1757 : n_pt_integ_path2 = int(epsilon/step)+1
1758 : else
1759 : n_pt_integ_path2 = 5
1760 : end if
1761 5238 : n_pt_integ_path2 = n_pt_integ
1762 5238 : dr_step = one/real(n_pt_integ_path2,dp)
1763 5238 : dz_path = -cmplx(zero,epsilon*dr_step,dp)
1764 534276 : path2: do ii = 0,n_pt_integ_path2
1765 : ! z_path = cmplx(xmin,real(ii,dp)*epsilon*dr_step,dp)
1766 529038 : z_path = cmplx(xmin,zero,dp)-dz_path*real(ii,dp)
1767 529038 : Nold = czero
1768 529038 : Dold = cone
1769 529038 : N = cone
1770 529038 : D = z_path - cmplx(an(0),zero,dp)
1771 :
1772 2116152 : do kk=1,nrec
1773 2116152 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1774 2116152 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1775 :
1776 2116152 : Nold = N
1777 2116152 : Dold = D
1778 2116152 : N = Nnew
1779 2116152 : D = Dnew
1780 :
1781 2645190 : if(kk/=nrec)then
1782 2116152 : if((bn2(kk+1)<tol14))exit
1783 : end if
1784 :
1785 : end do
1786 :
1787 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1788 529038 : delta_calc = func_rec(z_path,twotrotter)* N/D *dz_path
1789 534276 : if(ii==0.or.ii==n_pt_integ_path2)then
1790 10476 : ene_acc = ene_acc + half*delta_calc
1791 10476 : if(debug_rec) ene_acc3 = ene_acc3 + half*delta_calc
1792 : else
1793 518562 : ene_acc = ene_acc + delta_calc
1794 518562 : if(debug_rec) ene_acc3 = ene_acc3 + delta_calc
1795 : end if
1796 : end do path2
1797 :
1798 :
1799 :
1800 : !####################################################################
1801 : ![xmin,0]
1802 : if(xmin/=czero)then
1803 5238 : dr_step = one/real(n_pt_integ,dp)
1804 5238 : dz_path = cmplx(xmin*dr_step,zero,dp)
1805 529038 : path3: do ii = 1,n_pt_integ !the integrand is 0 at 0
1806 : ! z_path = cmplx(real(ii,dp)*xmin*dr_step,zero,dp)
1807 523800 : z_path = real(ii,dp)*dz_path
1808 :
1809 523800 : Nold = czero
1810 523800 : Dold = cone
1811 523800 : N = cone
1812 523800 : D = z_path - cmplx(an(0),zero,dp)
1813 :
1814 2095200 : do kk=1,nrec
1815 2095200 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1816 2095200 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1817 :
1818 2095200 : Nold = N
1819 2095200 : Dold = D
1820 2095200 : N = Nnew
1821 2095200 : D = Dnew
1822 :
1823 2619000 : if(kk/=nrec)then
1824 2095200 : if((bn2(kk+1)<tol14))exit
1825 : end if
1826 : end do
1827 :
1828 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1829 523800 : delta_calc = func_rec(z_path,twotrotter) * N/D *dz_path
1830 529038 : if(ii==n_pt_integ)then
1831 5238 : ene_acc = ene_acc +half*delta_calc
1832 5238 : if(debug_rec) ene_acc4 = ene_acc4 + half*delta_calc
1833 : else
1834 518562 : ene_acc = ene_acc + delta_calc
1835 518562 : if(debug_rec) ene_acc4 = ene_acc4 +delta_calc
1836 : end if
1837 : end do path3
1838 : end if
1839 :
1840 : !####################################################################
1841 : ![xmax,xmax+i*epsilon]
1842 534276 : dr_step = one/real(n_pt_integ_path2,dp)
1843 534276 : dz_path = cmplx(zero,epsilon*dr_step,dp)
1844 534276 : path4: do ii = 0,n_pt_integ_path2
1845 : ! z_path = cmplx(xmax,real(ii,dp)*epsilon*dr_step,dp)
1846 529038 : z_path = cmplx(xmax,0,dp)+real(ii,dp)*dz_path
1847 :
1848 529038 : Nold = czero
1849 529038 : Dold = cone
1850 529038 : N = cone
1851 529038 : D = z_path - cmplx(an(0),zero,dp)
1852 :
1853 2116152 : do kk=1,nrec
1854 2116152 : Nnew = (z_path - cmplx(an(kk),zero,dp))*N - cmplx(bn2(kk),zero,dp)*Nold
1855 2116152 : Dnew = (z_path - cmplx(an(kk),zero,dp))*D - cmplx(bn2(kk),zero,dp)*Dold
1856 :
1857 2116152 : Nold = N
1858 2116152 : Dold = D
1859 2116152 : N = Nnew
1860 2116152 : D = Dnew
1861 :
1862 2645190 : if(kk/=nrec)then
1863 2116152 : if((bn2(kk+1)<tol14))exit
1864 : end if
1865 :
1866 : end do
1867 :
1868 : ! <r|1/(z-e**(-beta/(2p)*(H-mu)))|r> dz
1869 529038 : delta_calc = func_rec(z_path,twotrotter) * N/D *dz_path
1870 534276 : if(ii==0.or.ii==n_pt_integ_path2)then
1871 10476 : ene_acc = ene_acc + half*delta_calc
1872 10476 : if(debug_rec) ene_acc2 = ene_acc2 + half*delta_calc
1873 : else
1874 518562 : ene_acc = ene_acc + delta_calc
1875 518562 : if(debug_rec) ene_acc2 = ene_acc2 + delta_calc
1876 : end if
1877 : end do path4
1878 :
1879 5238 : ene_out = mult*real(ene_acc*cmplx(zero,-piinv,dp),dp)
1880 5238 : if(debug_rec) then
1881 0 : ene_out1 = mult*real(ene_acc1*cmplx(zero,-piinv,dp),dp)
1882 0 : ene_out2 = mult*real(ene_acc2*cmplx(zero,-piinv,dp),dp)
1883 0 : ene_out3 = mult*real(ene_acc3*cmplx(zero,-piinv,dp),dp)
1884 0 : ene_out4 = mult*real(ene_acc4*cmplx(zero,-piinv,dp),dp)
1885 : end if
1886 :
1887 5238 : call timab(611,2,tsec)
1888 :
1889 : contains
1890 :
1891 : !func_rec(z_path,twotrotter) = log(cone+z_path**twotrotter)
1892 :
1893 2110914 : function func_rec(z,x)
1894 :
1895 : complex(dp) :: func_rec
1896 : complex(dp),intent(in) :: z
1897 : real(dp),intent(in) :: x
1898 :
1899 2110914 : func_rec = log(cone+z**x)
1900 :
1901 2110914 : end function func_rec
1902 :
1903 : end subroutine gran_potrec
1904 : !!***
1905 :
1906 : !!****f* ABINIT/nlenergyrec
1907 : !! NAME
1908 : !! nlenergyrec
1909 : !!
1910 : !! FUNCTION
1911 : !! During recursion, it computes the non-local energy
1912 : !!
1913 : !! INPUTS
1914 : !! rset<recursion_type>=contains all recursion parameters
1915 : !! exppot=exponential of -1/tsmear*vtrial (computed only once in vtorhorec)
1916 : !! tsmear=temperature (Hartree)
1917 : !! trotter=trotter parameter
1918 : !! tol=tolerance criteria for stopping recursion_nl
1919 : !! ngfft=information about FFT(dtset%ngfft a priori different from ngfftrec)
1920 : !! mpi_enreg=information about MPI paralelisation
1921 : !! rset<recursion_type> contains all parameter of recursion
1922 : !! typat(natom)=type of pseudo potential associated to any atom
1923 : !! natom=number of atoms
1924 : !!
1925 : !! OUTPUT
1926 : !! enlx=non-local energy
1927 : !!
1928 : !! SIDE EFFECTS
1929 : !!
1930 : !! NOTES
1931 : !!
1932 : !! SOURCE
1933 :
1934 0 : subroutine nlenergyrec(rset,enlx,exppot,ngfft,natom,typat,tsmear,trotter,tol)
1935 :
1936 : !Arguments ------------------------------------
1937 : !Scalar
1938 : integer , intent(in) :: natom,trotter
1939 : real(dp), intent(in) :: tsmear,tol
1940 : type(recursion_type),intent(in) :: rset
1941 : real(dp), intent(out) :: enlx
1942 : !Arrays
1943 : integer , intent(in) :: typat(natom),ngfft(18)
1944 : real(dp), intent(in) :: exppot(0:ngfft(1)*ngfft(2)*ngfft(3)-1)
1945 : !Local variables-------------------------------
1946 : integer :: iatom,jatom
1947 : integer :: ii,ipsp,dim_trott
1948 : integer :: ierr,me_count
1949 : integer :: ilmn,jlmn,ilm,jlm,in,jn,il
1950 : character(len=500) :: msg
1951 : logical :: tronc
1952 : real(dp) :: rho_nl,normali,mult
1953 0 : type(mpi_type):: mpi_loc
1954 : !Arrays
1955 0 : integer :: gcart_loc(3,natom)
1956 : integer :: ngfftrec(3),trasl(3)
1957 : real(dp) :: tsec(2)
1958 0 : real(dp) :: un0(0:rset%nfftrec)
1959 0 : real(dp),pointer :: projec(:,:,:,:,:)
1960 0 : real(dp),allocatable :: exppotloc(:)
1961 0 : real(dp) :: proj_arr(0:rset%ngfftrec(1)-1,0:rset%ngfftrec(2)-1,0:rset%ngfftrec(3)-1)
1962 :
1963 : ! *************************************************************************
1964 :
1965 :
1966 0 : call timab(612,1,tsec) !!--start time-counter: nlenergyrec
1967 :
1968 0 : if(rset%debug)then
1969 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' nlenergyrec : enter'
1970 0 : call wrtout(std_out,msg,'PERS')
1971 : end if
1972 :
1973 0 : write(msg,'(a)')' -- nlenergyrec -----------------------------------'
1974 0 : call wrtout(std_out,msg,'COLL')
1975 :
1976 : !--Initialisation variables
1977 0 : enlx = zero
1978 0 : mult = two !--is twice for non-spinned systems
1979 0 : ngfftrec = rset%ngfftrec(:3)
1980 0 : gcart_loc = rset%inf%gcart
1981 0 : mpi_loc = rset%mpi
1982 0 : me_count = 0
1983 0 : dim_trott = max(0,2*trotter-1)
1984 : nullify(projec)
1985 0 : ABI_MALLOC(projec,(0:rset%ngfftrec(1)-1,0:rset%ngfftrec(2)-1,0:rset%ngfftrec(3)-1,rset%nl%lmnmax,natom))
1986 0 : projec = zero
1987 :
1988 0 : tronc = rset%tronc !--True if troncation is used
1989 0 : if(tronc) then
1990 0 : ABI_MALLOC(exppotloc,(0:rset%nfftrec-1))
1991 : end if
1992 :
1993 :
1994 : !--LOOP ON ATOMS to create projectors-vector
1995 0 : atomloop1: do iatom = 1, natom
1996 0 : ipsp = typat(iatom)
1997 : ! --Aquisition,reshape,translation,rotation of the projectors vector
1998 0 : do ilmn = 1,rset%nl%lmnmax
1999 0 : in = rset%nl%indlmn(3,ilmn,ipsp)
2000 : ! --Projectors vector in 3-composant vector
2001 0 : projec(:,:,:,ilmn,iatom) = reshape(rset%nl%projec(:,ilmn,ipsp),shape=shape(projec(:,:,:,1,1)))
2002 : ! --Moving the projectors vector on the center of the grid
2003 0 : do ii=1,3
2004 0 : projec(:,:,:,ilmn,iatom) = cshift(projec(:,:,:,ilmn,iatom),shift=ngfftrec(ii)/2-gcart_loc(ii,iatom),dim=ii)
2005 : end do
2006 : end do
2007 :
2008 : end do atomloop1
2009 :
2010 :
2011 : !##################################################################
2012 : !--LOOP ON ATOMS (MAIN LOOP)
2013 0 : atomloop: do iatom = 1, natom
2014 0 : ipsp = typat(iatom)
2015 :
2016 : ! --If troncation is present, the considered atom has to be in the
2017 : ! center of the grid so atoms, potential and projectors have to be translated
2018 0 : if(tronc) then
2019 0 : trasl = -rset%inf%gcart(:,iatom)+ngfftrec/2
2020 : ! --Translation of atoms
2021 0 : do jatom=1,natom
2022 0 : gcart_loc(:,jatom) = rset%inf%gcart(:,jatom)+trasl
2023 0 : gcart_loc(:,jatom) = modulo(gcart_loc(:,jatom),ngfft(:3))
2024 : ! --Translation of non-local projectors
2025 0 : do ilmn = 1,rset%nl%lmnmax
2026 0 : projec(:,:,:,ilmn,jatom) = reshape(rset%nl%projec(:,ilmn,typat(jatom)),shape=shape(projec(:,:,:,1,1)))
2027 0 : do ii=1,3
2028 0 : projec(:,:,:,ilmn,jatom) = eoshift(projec(:,:,:,ilmn,jatom),shift=ngfftrec(ii)/2-gcart_loc(ii,jatom),dim=ii)
2029 : end do
2030 : end do
2031 : end do
2032 :
2033 : ! --Translation of the potential
2034 0 : call reshape_pot(trasl,ngfft(1)*ngfft(2)*ngfft(3),rset%nfftrec,ngfft(:3),ngfftrec,exppot,exppotloc)
2035 : end if
2036 :
2037 : ! --Loop on projectors
2038 0 : projloop: do ilmn = 1,rset%nl%lmnmax
2039 0 : me_count = iatom+ilmn*natom-2 !--counter of the number of iteration
2040 : ! --Only the proc me compute
2041 0 : if(mpi_loc%me==mod(me_count,mpi_loc%nproc)) then
2042 0 : ilm = rset%nl%indlmn(4,ilmn,ipsp)
2043 0 : proj_arr = zero
2044 0 : do jlmn = 1,rset%nl%lmnmax
2045 0 : jlm = rset%nl%indlmn(4,jlmn,ipsp)
2046 0 : if(ilm==jlm) then
2047 0 : in = rset%nl%indlmn(3,ilmn,ipsp)
2048 0 : jn = rset%nl%indlmn(3,jlmn,ipsp)
2049 0 : il = rset%nl%indlmn(1,ilmn,ipsp)+1
2050 0 : proj_arr(:,:,:) = proj_arr(:,:,:) + rset%nl%eivec(jn,in,il,ipsp)*projec(:,:,:,jlmn,iatom)
2051 : ! write(std_out,*)'l,m,lm,n,n',il-1,rset%nl%indlmn(2,ilmn,ipsp),ilm,in,jn
2052 : ! write(std_out,*)'eigevectors',rset%nl%eivec(jn,in,il,ipsp)
2053 :
2054 : end if
2055 : end do
2056 :
2057 0 : un0 = pack(proj_arr(:,:,:),mask=.true.)
2058 0 : normali = sum(un0*un0)*rset%inf%ucvol
2059 0 : un0 = (one/sqrt(normali))*un0
2060 :
2061 0 : if(tronc)then
2062 : call recursion_nl(exppotloc,un0,rho_nl,rset,rset%ngfftrec,&
2063 : & tsmear,trotter,dim_trott,tol,typat,&
2064 0 : & natom,projec)
2065 : else
2066 : call recursion_nl(exppot,un0,rho_nl,rset,rset%ngfftrec,&
2067 : & tsmear,trotter,dim_trott,tol,typat,&
2068 0 : & natom,projec)
2069 : end if
2070 :
2071 0 : enlx = enlx+mult*rho_nl*rset%nl%eival(in,il,ipsp)*normali
2072 : end if
2073 :
2074 : end do projloop
2075 : end do atomloop
2076 :
2077 : !--Sum the contribution to the non-local energy computed by any procs
2078 0 : call xmpi_sum(enlx,mpi_loc%comm_bandfft,ierr)
2079 :
2080 0 : if(associated(projec)) then
2081 0 : ABI_FREE(projec)
2082 : end if
2083 0 : if(tronc) then
2084 0 : ABI_FREE(exppotloc)
2085 : end if
2086 :
2087 0 : if(rset%debug)then
2088 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' nlenergyrec : exit'
2089 0 : call wrtout(std_out,msg,'PERS')
2090 : end if
2091 :
2092 0 : call timab(612,2,tsec) !--stop time-counter: nlenergyrec
2093 :
2094 0 : end subroutine nlenergyrec
2095 : !!***
2096 :
2097 :
2098 : !!****f* ABINIT/first_rec
2099 : !! NAME
2100 : !! first_rec
2101 : !!
2102 : !! FUNCTION
2103 : !! When recursion method is used, in the first step this routine
2104 : !! compute some quantities which are used in the rest of the calculation.
2105 : !!
2106 : !! COPYRIGHT
2107 : !! Copyright (C) 2009-2026 ABINIT group (MMancini)
2108 : !! This file is distributed under the terms of the
2109 : !! GNU General Public License, see ~abinit/COPYING
2110 : !! or http://www.gnu.org/copyleft/gpl.txt .
2111 : !!
2112 : !! INPUTS
2113 : !! dtset <type(dataset_type)>=all input variables for this dataset:
2114 : !! | recgratio =fine/coarse grid ratio
2115 : !! | recptrott =trotter parameter
2116 : !! | tsmear =temperature
2117 : !! | recrcut =tut radius in recursion (range of iteration)
2118 : !! | ngfft(18) =FFT grid used as real (fine) grid in recursion
2119 : !! psps <type(pseudopotential_type)>=variables related to pseudo-potentials
2120 : !!
2121 : !! OUTPUT
2122 : !!
2123 : !! SIDE EFFECTS
2124 : !! rset <type(recursion_type)>=variables related to recursion method
2125 : !! | debug<logical> = T if debugging is used
2126 : !! | inf <type(metricrec_type)>=information concerning the infinitesimal metrics
2127 : !! | ngfftrec(18) =truncated (or not, if not ngfftrec=ngfft)FFT grid used as real grid in recursion.
2128 : !! | nfftrec =product(ngfftrec(1:3))
2129 : !! | tronc<logical> = T if truncation is effectively used
2130 : !! | ZT_p = fourier transform of the green_kernel calculated on the fine grid
2131 : !!
2132 : !!
2133 : !! NOTES
2134 : !!
2135 : !! SOURCE
2136 :
2137 6 : subroutine first_rec(dtset,psps,rset)
2138 :
2139 : !Arguments ------------------------------------
2140 : ! scalars
2141 : type(dataset_type),intent(in) :: dtset
2142 : type(pseudopotential_type),intent(in) :: psps
2143 : type(recursion_type),intent(inout) :: rset
2144 : !Local variables-------------------------------
2145 : !scalars
2146 : integer :: nfftrec,trotter,ii,dim_trott
2147 : real(dp) :: tsmear,beta,rtrotter
2148 : character(len=500) :: msg
2149 : !arrays
2150 : integer :: ngfftrec(18)
2151 : real(dp) :: tsec(2)
2152 : #ifdef HAVE_GPU_CUDA
2153 : integer :: max_rec,ierr,testpts,swt_tm
2154 : real(dp) :: rho,tm_ratio
2155 : real(dp) :: time_cu,time_f
2156 : type(recursion_type) :: rset_test
2157 : type(recparall_type) :: parold
2158 : integer :: trasl(3)
2159 : real(dp) :: tsec2(2),tsec3(2)
2160 : real(dp) :: aloc(0,1),b2loc(0,1)
2161 : real(dp) :: dm_projec(0,0,0,1,1)
2162 : real(dp) :: exppot(0:dtset%nfft-1)
2163 : real(dp),allocatable :: exppotloc(:)
2164 : real(cudap),allocatable :: aloc_cu(:),b2loc_cu(:)
2165 : #endif
2166 :
2167 : ! *************************************************************************
2168 :
2169 6 : call timab(601,1,tsec) !!--Start time-counter: initialisation
2170 :
2171 6 : ABI_WARNING("RECURSION")
2172 6 : if(dtset%recgratio>1) then
2173 1 : write(msg,'(a)')'COARSE GRID IS USED'
2174 1 : call wrtout(std_out,msg,'COLL')
2175 : end if
2176 :
2177 : !--Initialisation
2178 6 : trotter = dtset%recptrott !--Trotter parameter
2179 6 : tsmear = dtset%tsmear !--Temperature
2180 6 : beta = one/tsmear !--Inverse of temperature
2181 :
2182 : !--Rewriting the trotter parameter
2183 6 : dim_trott = max(0,2*trotter-1)
2184 6 : rtrotter = max(half,real(trotter,dp))
2185 :
2186 6 : write (msg,'(2a)')ch10,'==== FIRST CYCLE RECURSION ========================='
2187 6 : call wrtout(std_out,msg,'COLL')
2188 :
2189 :
2190 114 : ngfftrec = rset%ngfftrec
2191 6 : nfftrec = rset%nfftrec
2192 : !------------------------------------------------
2193 : !--TRONCATION OF THE BOX: determines new dimensions
2194 : !--Now in InitRec
2195 : !--------------------------------------------------------
2196 : !--DEFINITION PAW VARIABLES COARSE-FINE GRID TO USE TRANSGRID--INGRID FUNCTIONS
2197 : !--Now these variables are defined into gstate by InitRec
2198 :
2199 : !--------------------------------------------------------
2200 : !--COMPUTATION OF THE FOURIER TRANSFORM OF THE GREEN KERNEL (only once)
2201 6 : write (msg,'(a)')' - green kernel calculation -----------------------'
2202 6 : call wrtout(std_out,msg,'COLL')
2203 18 : ABI_MALLOC(rset%ZT_p,(1:2,0: nfftrec-1))
2204 6 : call timab(601,2,tsec)
2205 6 : call green_kernel(rset%ZT_p,rset%inf%rmet,rset%inf%ucvol,rtrotter/beta,rset%mpi,ngfftrec,nfftrec)
2206 6 : call timab(601,1,tsec)
2207 306 : write(msg,'(a,50a)')' ',('-',ii=1,50)
2208 6 : call wrtout(std_out,msg,'COLL')
2209 : !!--end computation of the fourier transform of the Green kernel
2210 :
2211 : !!-----------------------------------
2212 : !!--ROUTINE FOR THE CALCULATION OF THE NON-LOCAL PSEUDO
2213 : !--Now these variables here by Init_nlpspRec
2214 6 : call Init_nlpspRec(four*tsmear*rtrotter,psps,rset%nl,rset%inf,rset%ngfftrec,rset%debug)
2215 :
2216 : !!-----------------------------------
2217 : !--Load distribution on procs when GPU are present
2218 : #if defined HAVE_GPU_CUDA
2219 :
2220 : !--Test timing only if exists GPU and they are not equal to the cpus
2221 : if(rset%tp == 4) then
2222 : parold = rset%par
2223 : ii = 0
2224 : time_f = zero
2225 : time_cu = zero
2226 : call random_number(exppot) ! exppot = one
2227 :
2228 : if(rset%gpudevice == -1) then
2229 : ! --Test CPUS
2230 : swt_tm = 0
2231 : testpts = min(rset%par%npt, 20)
2232 : call timein(tsec2(1),tsec2(2))
2233 : if(rset%tronc) then
2234 : ABI_MALLOC(exppotloc,(0:nfftrec-1))
2235 : do while(ii< testpts)
2236 : trasl = -(/1,2,3/)+ngfftrec(:3)/2
2237 : call reshape_pot(trasl,dtset%nfft,nfftrec,dtset%ngfft(:3),ngfftrec(:3),&
2238 : & exppot,exppotloc)
2239 : call recursion(exppotloc,0,0,0, &
2240 : & aloc, &
2241 : & b2loc, &
2242 : & rho,&
2243 : & 0, rset%efermi,tsmear,rtrotter,dim_trott, &
2244 : & rset%ZT_p, &
2245 : & dtset%rectolden,dtset%typat, &
2246 : & rset%nl,&
2247 : & rset%mpi,nfftrec,ngfftrec,rset%inf,&
2248 : & 6,dtset%natom,dm_projec,0)
2249 : ii=ii+1
2250 : end do
2251 : ABI_FREE(exppotloc)
2252 : else
2253 : do while(ii< testpts)
2254 : call recursion(exppot,0,0,0, &
2255 : & aloc, &
2256 : & b2loc, &
2257 : & rho,&
2258 : & 0, rset%efermi,tsmear,rtrotter,dim_trott, &
2259 : & rset%ZT_p, &
2260 : & dtset%rectolden,dtset%typat, &
2261 : & rset%nl,&
2262 : & rset%mpi,nfftrec,ngfftrec,rset%inf,&
2263 : & 6,dtset%natom,dm_projec,0)
2264 : ii=ii+1
2265 : end do
2266 : end if
2267 : call timein(tsec3(1),tsec3(2))
2268 : time_f = (tsec3(1)-tsec2(1))/real(testpts,dp)
2269 : time_f = time_f*time_f
2270 : else
2271 : ! --Test GPUS
2272 : swt_tm = 1
2273 : rset_test = rset
2274 : rset_test%GPU%par%npt = max(rset%GPU%nptrec,100)
2275 : rset_test%min_nrec = 0
2276 : call get_pt0_pt1(dtset%ngfft(:3),dtset%recgratio,0,&
2277 : & rset_test%GPU%par%npt,rset_test%GPU%par)
2278 :
2279 :
2280 : ABI_MALLOC(aloc_cu,(rset_test%GPU%par%npt))
2281 : ABI_MALLOC(b2loc_cu,(rset_test%GPU%par%npt))
2282 : call timein(tsec2(1),tsec2(2))
2283 : call cudarec(rset_test, exppot,aloc_cu,b2loc_cu,&
2284 : & beta,trotter,dtset%rectolden,dtset%recgratio,dtset%ngfft,max_rec)
2285 : call timein(tsec3(1),tsec3(2))
2286 : ABI_FREE(aloc_cu)
2287 : ABI_FREE(b2loc_cu)
2288 :
2289 : time_cu = (tsec3(1)-tsec2(1))/real(rset_test%GPU%par%npt,dp)
2290 : time_cu = time_cu*time_cu
2291 : end if
2292 :
2293 :
2294 : ! --Get Total Times
2295 : call xmpi_sum(time_f,rset%mpi%comm_bandfft,ierr)
2296 : call xmpi_sum(time_cu,rset%mpi%comm_bandfft,ierr)
2297 :
2298 : ! --Average Total Times
2299 : time_f = sqrt(time_f/real(rset%mpi%nproc-rset%ngpu,dp))
2300 : time_cu = sqrt(time_cu/real(rset%ngpu,dp))
2301 : tm_ratio = time_f/time_cu
2302 :
2303 :
2304 : write(msg,'(3(a25,f10.5,a))')&
2305 : & ' Time for cpu recursion ',time_f,ch10,&
2306 : & ' Time for gpu recursion ',time_cu,ch10,&
2307 : & ' Time ratio ',tm_ratio,ch10
2308 : call wrtout(std_out,msg,'COLL')
2309 :
2310 :
2311 : ! tm_ratio =1.20d2! 0.d0! 1.21d0
2312 : rset%par = parold
2313 : ! --Compute the work-load distribution on devices (gpu,cpu)
2314 : if(tm_ratio>1.5d0 .and. time_cu>zero)then
2315 : rset%load = 1
2316 : call cpu_distribution(dtset%recgratio,rset,dtset%ngfft(:3),tm_ratio,1)
2317 : else
2318 : rset%gpudevice = -1
2319 : end if
2320 : end if
2321 :
2322 : #endif
2323 :
2324 :
2325 : !------------------------------------------------------------
2326 : !--DETERMINING WHICH POINT WILL COMPUTE THAT PROC
2327 : !--Now these variables are defined into gstate by Init_rec
2328 :
2329 6 : write (msg,'(2a)')ch10,'==== END FIRST CYCLE RECURSION ====================='
2330 6 : call wrtout(std_out,msg,'COLL')
2331 6 : call timab(601,2,tsec) !!--stop time-counter: initialisation
2332 :
2333 6 : end subroutine first_rec
2334 : !!***
2335 :
2336 :
2337 : !!****f* ABINIT/green_kernel
2338 : !! NAME
2339 : !! green_kernel
2340 : !!
2341 : !! FUNCTION
2342 : !! this routine compute the fourrier transform of the Green kernel for the
2343 : !! recursion method
2344 : !!
2345 : !! INPUTS
2346 : !! inf_rmet=define the infinitesimal metric : rprimd*(transpose(rprimd)) divided
2347 : !! by the number of discretisation point
2348 : !! inf_ucvol=volume of infinitesimal cell
2349 : !! mult=variance of the Gaussian (=rtrotter/beta)
2350 : !! mpi_enreg=information about MPI parallelization
2351 : !! ngfft=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
2352 : !! nfft=total number of fft grid points
2353 : !! debug_rec=debugging variable
2354 : !!
2355 : !! OUTPUT
2356 : !! ZT_p=fourier transforme of the Green kernel
2357 : !!
2358 : !! NOTES
2359 : !! at this time :
2360 : !! - need a rectangular box
2361 : !!
2362 : !! SOURCE
2363 :
2364 :
2365 6 : subroutine green_kernel(ZT_p,inf_rmet,inf_ucvol,mult,mpi_enreg,ngfft,nfft)
2366 :
2367 : !Arguments -------------------------------
2368 : !scalars
2369 : integer,intent(in) :: nfft
2370 : real(dp),intent(in) :: inf_ucvol,mult
2371 : type(MPI_type),intent(in) :: mpi_enreg
2372 : !arrays
2373 : integer,intent(in) :: ngfft(18)
2374 : real(dp),intent(in) :: inf_rmet(3,3)
2375 : real(dp),intent(out) :: ZT_p(1:2,0:nfft-1)
2376 :
2377 : !Local variables-------------------------------
2378 : !scalars
2379 : integer,parameter :: n_green_max=5
2380 : integer :: ii,isign,jj,kk,n_green,xx,yy,zz
2381 : real(dp) :: acc, norme
2382 : character(len=500) :: msg
2383 : !arrays
2384 : real(dp) :: tsec(2)
2385 6 : real(dp),allocatable :: T_p(:)
2386 :
2387 : ! *************************************************************************
2388 :
2389 6 : call timab(603,1,tsec)
2390 :
2391 6 : norme = (mult/pi)**(onehalf)
2392 :
2393 18 : ABI_MALLOC(T_p,(0:nfft-1))
2394 :
2395 : !n_green should be better chosen for non rectangular cell
2396 6 : do xx=1, n_green_max
2397 6 : n_green = xx
2398 : if(exp(-mult*dsq_green(xx*ngfft(1),0,0,inf_rmet))<tol14 &
2399 : & .and. exp(-mult*dsq_green(0,xx*ngfft(2),0,inf_rmet))<tol14 &
2400 6 : & .and. exp(-mult*dsq_green(0,0,xx*ngfft(3),inf_rmet))<tol14 ) exit
2401 : end do
2402 :
2403 8710 : acc = zero
2404 8710 : T_p = zero
2405 70 : do kk = 0,ngfft(3)-1
2406 806 : do jj = 0,ngfft(2)-1
2407 9504 : do ii = 0,ngfft(1)-1
2408 :
2409 26112 : do xx=-n_green,n_green-1
2410 60928 : do yy=-n_green,n_green-1
2411 121856 : do zz=-n_green,n_green-1
2412 :
2413 : T_p(ii+ngfft(1)*jj+ngfft(1)*ngfft(2)*kk) = T_p(ii+ngfft(1)*jj+ngfft(1)*ngfft(2)*kk)+ &
2414 104448 : & exp(-mult*dsq_green(ii+xx*ngfft(1),jj+yy*ngfft(2),kk+zz*ngfft(3),inf_rmet))
2415 :
2416 : end do
2417 : end do
2418 : end do
2419 :
2420 8704 : T_p(ii+ngfft(1)*jj+ngfft(1)*ngfft(2)*kk) = norme*T_p(ii+ngfft(1)*jj+ngfft(1)*ngfft(2)*kk)
2421 9440 : acc = acc + inf_ucvol* T_p(ii+ngfft(1)*jj+ngfft(1)*ngfft(2)*kk)
2422 :
2423 : end do
2424 : end do
2425 : end do
2426 :
2427 8710 : T_p(:)= (one/acc)*T_p(:)
2428 :
2429 : !if(debug_rec)then
2430 : write(msg,'(a,d12.3,2(2a,i8),2(2a,3d12.3),2a,d16.6)')&
2431 6 : & ' on the boundary ', exp(-mult*dsq_green(ngfft(1),0,0,inf_rmet)),ch10, &
2432 8710 : & ' no zero ', count(T_p>tol14),ch10, &
2433 6 : & ' n_green ', n_green,ch10, &
2434 6 : & ' erreur_n_green ', exp(-mult*dsq_green(n_green*ngfft(1),0,0,inf_rmet)), &
2435 6 : & exp(-mult*dsq_green(0,n_green*ngfft(2),0,inf_rmet)), &
2436 6 : & exp(-mult*dsq_green(0,0,n_green*ngfft(3),inf_rmet)),ch10,&
2437 6 : & ' erreur_troncat ', T_p(ngfft(1)/2), &
2438 6 : & T_p(ngfft(1)*(ngfft(2)/2)), &
2439 6 : & T_P(ngfft(1)*ngfft(2)*(ngfft(3)/2)),ch10, &
2440 12 : & ' erreurT_p ',abs(acc-1.d0)
2441 6 : call wrtout(std_out,msg,'COLL')
2442 : !endif
2443 :
2444 :
2445 6 : isign = -1
2446 6 : call fourdp(1,ZT_p,T_p,isign,mpi_enreg,nfft,1,ngfft,0)
2447 :
2448 6 : ABI_FREE(T_p)
2449 :
2450 26118 : ZT_p(:,:) = real(nfft,dp)*ZT_p
2451 :
2452 :
2453 6 : call timab(603,2,tsec)
2454 :
2455 : contains
2456 :
2457 69674 : function dsq_green(ii,jj,kk,inf_rmet)
2458 :
2459 : real(dp) :: dsq_green
2460 : integer,intent(in) :: ii,jj,kk
2461 : real(dp),intent(in) :: inf_rmet(3,3)
2462 : dsq_green= inf_rmet(1,1)*dble(ii**2)&
2463 : & +inf_rmet(2,2)*dble(jj**2)&
2464 : & +inf_rmet(3,3)*dble(kk**2)&
2465 : & +two*(inf_rmet(1,2)*dble(ii*jj)&
2466 : & +inf_rmet(2,3)*dble(jj*kk)&
2467 69674 : & +inf_rmet(3,1)*dble(kk*ii))
2468 69674 : end function dsq_green
2469 :
2470 : end subroutine green_kernel
2471 : !!***
2472 :
2473 :
2474 : !!****f* ABINIT/recursion
2475 : !! NAME
2476 : !! recursion
2477 : !!
2478 : !! FUNCTION
2479 : !! This routine computes the recursion coefficients and the corresponding
2480 : !! continued fraction to get the density at a point from a fixed potential.
2481 : !!
2482 : !! INPUTS
2483 : !! exppot=exponential of -1/tsmear*vtrial (computed only once in vtorhorec)
2484 : !! coordx, coordy, coordz=coordonnees of the computed point
2485 : !! nrec=order of recursion
2486 : !! fermie=fermi energy (Hartree)
2487 : !! tsmear=temperature (Hartree)
2488 : !! dim_trott=dimension of the partial fraction decomposition
2489 : !! rtrotter=trotter parameter (real)
2490 : !! ZT_p=fourier transform of the Green krenel (computed only once in vtorhorec)
2491 : !! typat(:)=type of psp associated to any atom
2492 : !! tol=tolerance criteria for stopping recursion
2493 : !! debug=debugging variable
2494 : !! mpi_enreg=information about MPI paralelisation
2495 : !! nfft=number of points in FFT grid
2496 : !! ngfft=information about FFT
2497 : !! metrec<type(metricrec_type)>=information concerning the infinitesimal metrics
2498 : !! inf_ucvol=infinitesimal unit cell volume
2499 : !! tim_fourdp=time counter for fourdp
2500 : !! natom=number of atoms
2501 : !! projec(ngfftrec(1),ngfftrec(2),ngfftrec(3),lmnmax,natom) is the vector, on the ngfftrec grid containing
2502 : !! the non-lacal projector $Y_{lm}(r-R_A)f_{lk}(r-R_A)
2503 : !! tim= 0 if the time spent in the routine is not taken into account,1 otherwise. For example
2504 : !! when measuring time for loading balancing, we don't want to add the time spent in this to the
2505 : !! total time calculation
2506 : !!
2507 : !! OUTPUT
2508 : !! rho_out=result of the continued fraction multiplied by a multiplicator
2509 : !! an, bn2 : coefficient given by recursion.
2510 : !!
2511 : !! SIDE EFFECTS
2512 : !!
2513 : !! NOTES
2514 : !! at this time :
2515 : !! - exppot should be replaced by ?
2516 : !! - coord should be replaced by ?
2517 : !! - need a rectangular box (rmet diagonal matrix)
2518 : !!
2519 : !! SOURCE
2520 :
2521 17469 : subroutine recursion(exppot,coordx,coordy,coordz,an,bn2,rho_out, &
2522 : & nrec,fermie,tsmear,rtrotter,dim_trott, &
2523 34938 : & ZT_p, tol,typat, &
2524 : & nlrec,mpi_enreg,&
2525 : & nfft,ngfft,metrec,&
2526 17469 : & tim_fourdp,natom,projec,tim)
2527 :
2528 :
2529 : use m_linalg_interfaces
2530 :
2531 : !Arguments -------------------------------
2532 : !scalars
2533 : integer,intent(in) :: coordx,coordy,coordz,nfft,nrec,tim
2534 : integer,intent(in) :: tim_fourdp,natom,dim_trott
2535 : real(dp),intent(in) :: fermie,tol,tsmear,rtrotter
2536 : real(dp), intent(out) :: rho_out
2537 : type(MPI_type),intent(in) :: mpi_enreg
2538 : type(nlpsprec_type),intent(in) :: nlrec
2539 : type(metricrec_type),intent(in) :: metrec
2540 : !arrays
2541 : integer, intent(in) :: ngfft(18)
2542 : integer, intent(in) :: typat(natom)
2543 : real(dp), intent(in) :: ZT_p(1:2, 0:nfft-1)
2544 : real(dp), intent(in) :: exppot(0:nfft-1)
2545 : real(dp), intent(in) :: projec(0:,0:,0:,1:,1:)
2546 : real(dp), intent(out) :: an(0:nrec),bn2(0:nrec)
2547 : !Local variables-------------------------------
2548 : !not used, debugging purpose only
2549 : !for debugging purpose, detailled printing only once for density and ekin
2550 : !scalars
2551 : integer, parameter :: level = 7, minrec = 3
2552 : integer :: irec,isign,timab_id,ii
2553 : real(dp) :: switchimu,switchu
2554 : real(dp) :: bb,beta,mult,prod_b2,error,errold
2555 : real(dp) :: inf_ucvol,pi_on_rtrotter,twortrotter,exp1,exp2
2556 : complex(dp) :: cinv2rtrotter,coeef_mu,facrec0
2557 : ! character(len=500) :: msg
2558 : !arrays
2559 : real(dp) :: tsec(2)
2560 : real(dp) :: inf_tr(3)
2561 34938 : real(dp) :: Zvtempo(1:2, 0:nfft-1)
2562 34938 : real(dp) :: unold(0:nfft-1),vn(0:nfft-1),un(0:nfft-1)
2563 34938 : complex(dp) :: acc_rho(0:nrec)
2564 34938 : complex(dp) :: D(0:dim_trott),Dold(0:dim_trott)
2565 34938 : complex(dp) :: N(0:dim_trott),Nold(0:dim_trott)
2566 : ! *************************************************************************
2567 :
2568 : !--If count time or not
2569 17469 : timab_id = 616; if(tim/=0) timab_id = 606;
2570 :
2571 17469 : call timab(timab_id,1,tsec)
2572 :
2573 : !##############################################################
2574 : !--Initialisation of metrics
2575 17469 : inf_ucvol = metrec%ucvol
2576 : inf_tr = metrec%tr
2577 17469 : mult = two/inf_ucvol !non-spined system
2578 :
2579 17469 : beta = one/tsmear
2580 : !--Variables for optimisation
2581 17469 : pi_on_rtrotter = pi/rtrotter
2582 17469 : twortrotter = two*rtrotter
2583 17469 : exp1 = exp((beta*fermie)/(rtrotter))
2584 17469 : exp2 = exp(beta*fermie/(twortrotter))
2585 17469 : cinv2rtrotter = cmplx(one/twortrotter,zero,dp)
2586 17469 : coeef_mu = cmplx(one/exp2,zero,dp)
2587 :
2588 : !--Initialisation of an,bn,un....
2589 716229 : N = czero; D = cone
2590 17469 : facrec0 = cone
2591 716229 : Nold = czero; Dold = czero
2592 :
2593 568539 : an = zero; bn2 = zero; bn2(0) = one
2594 59761341 : bb = zero; vn = zero; unold = zero
2595 : !--u0 is a Dirac function
2596 29889405 : un = zero
2597 17469 : un(coordx+ngfft(1)*(coordy+ngfft(2)*coordz)) = one/sqrt(inf_ucvol)
2598 :
2599 : !--Initialisation of accumulated density
2600 293004 : acc_rho = czero
2601 : !--Initialisation of estimated error
2602 17469 : prod_b2 = twortrotter/exp1
2603 17469 : errold = zero
2604 :
2605 : !##############################################################
2606 : !--Main loop
2607 69876 : maindo : do irec = 0, nrec
2608 :
2609 : ! --Get an and bn2 coef by the lanczos method
2610 :
2611 : ! --Computation of exp(-beta*V/8*p)*un or exp(-beta*V/4*p)*un
2612 : ! depending on if nl part has to be calculated or not.
2613 119557620 : vn = exppot * un
2614 :
2615 : ! --First Non-local psp contribution: (Id+sum_atom int dr1(E(r,r1))vn(r1))
2616 : ! --Computation of exp(-beta*V_NL/4*p)*vn
2617 69876 : if(nlrec%nlpsp) then
2618 0 : call timab(timab_id,2,tsec)
2619 0 : call vn_nl_rec(vn,natom,typat,ngfft(:3),inf_ucvol,nlrec,projec)
2620 0 : call timab(timab_id,1,tsec)
2621 :
2622 : ! --Computation of exp(-beta*V/8*p)*vn in nonlocal case
2623 0 : vn = exppot * vn
2624 : end if !--End if on nlrec%nlpsp
2625 :
2626 : ! --Convolution with the Green kernel
2627 : ! --FFT of vn
2628 69876 : isign = -1
2629 69876 : call fourdp(1,Zvtempo,vn,isign,mpi_enreg,nfft,1,ngfft,tim_fourdp)
2630 :
2631 : ! --F(T)F(vn)
2632 119557620 : do ii = 0,nfft-1
2633 119487744 : switchu = Zvtempo(1,ii)
2634 119487744 : switchimu = Zvtempo(2,ii)
2635 119487744 : Zvtempo(1,ii) = switchu*ZT_p(1,ii) - switchimu*ZT_p(2,ii)
2636 119557620 : Zvtempo(2,ii) = switchu*ZT_p(2,ii) + switchimu*ZT_p(1,ii)
2637 : end do
2638 :
2639 : ! --F^-1(F(T)F(vn))
2640 69876 : isign = 1
2641 69876 : call fourdp(1,Zvtempo,vn,isign,mpi_enreg,nfft,1,ngfft,tim_fourdp)
2642 :
2643 : ! --Computation of exp(-beta*V/8*p)*un or exp(-beta*V/4*p)*un
2644 : ! depending on if nl part has to be calculated or not.
2645 :
2646 119557620 : vn = inf_ucvol * exppot * vn
2647 :
2648 : ! --Second Non-local psp contribution: (Id+sum_atom E(r,r1))vn
2649 69876 : if(nlrec%nlpsp) then
2650 0 : call timab(timab_id,2,tsec)
2651 0 : call vn_nl_rec(vn,natom,typat,ngfft(:3),inf_ucvol,nlrec,projec)
2652 0 : call timab(timab_id,1,tsec)
2653 :
2654 : ! --Computation of exp(-beta*V/8*p)*vn in nonlocal case
2655 0 : vn = exppot * vn
2656 : end if !--End if on nlrec%nlpsp
2657 :
2658 : ! --Multiplication of a and b2 coef by exp(beta*fermie/(two*rtrotter)) must be done in the continued fraction computation
2659 : ! --Computation of a and b2
2660 69876 : an(irec) = inf_ucvol*ddot(nfft,vn,1,un,1)
2661 :
2662 : ! --an must be positive real
2663 : ! --We must compute bn2 and prepare for the next iteration
2664 69876 : if(irec<nrec)then
2665 119557620 : do ii = 0,nfft-1
2666 119487744 : switchu = un(ii)
2667 119487744 : un(ii) = vn(ii)-an(irec)*un(ii)-bb*unold(ii)
2668 119487744 : unold(ii) = switchu
2669 119557620 : bn2(irec+1) = bn2(irec+1)+inf_ucvol*un(ii)*un(ii)
2670 : end do
2671 69876 : bb = sqrt(bn2(irec+1))
2672 119557620 : un = (one/bb)*un
2673 : end if
2674 :
2675 : ! ######################################################
2676 : ! --Density computation
2677 : ! density computation is done inside the main looping, juste after the calculus of a and b2, in order to make
2678 : ! it possible to stop the recursion at the needed accuracy, without doing more recursion loop than needed -
2679 : ! further developpement
2680 :
2681 : ! !--using the property that: sum_i(bi*c)^2|(z-ai*c)=1/c*sum_i(bi)^2|(z/c-ai)
2682 : ! !and for c =exp(-beta*fermie/(two*rtrotter)
2683 :
2684 :
2685 : call trottersum(dim_trott,error,prod_b2,pi_on_rtrotter,&
2686 : & facrec0,coeef_mu,exp1,&
2687 : & an(irec),bn2(irec),&
2688 69876 : & N,D,Nold,Dold)
2689 :
2690 :
2691 69876 : if(irec/=nrec .and. irec>=minrec)then
2692 17469 : if((bn2(irec+1)<tol14).or.(mult*error<tol.and.errold<tol)) exit
2693 : end if
2694 69876 : errold = mult*error
2695 : end do maindo
2696 : !--Accumulated density
2697 366849 : rho_out = mult*real(cone-sum(N/D)*cinv2rtrotter,dp)
2698 :
2699 :
2700 17469 : call timab(timab_id,2,tsec)
2701 :
2702 17469 : end subroutine recursion
2703 : !!***
2704 :
2705 :
2706 : !!****f* ABINIT/recursion_nl
2707 : !! NAME
2708 : !! recursion_nl
2709 : !!
2710 : !! FUNCTION
2711 : !! Given a $|un>$ vector on the real-space grid this routine calculates
2712 : !! the density in $|un>$ by recursion method.
2713 : !!
2714 : !! INPUTS
2715 : !! exppot=exponential of -1/tsmear*vtrial (computed only once in vtorhorec)
2716 : !! trotter=trotter parameter
2717 : !! dim_trott=dimension of the partial fraction decomposition
2718 : !! tsmear=temperature (Hartree)
2719 : !! tol=tolerance criteria for stopping recursion_nl
2720 : !! ngfft=information about FFT(dtset%ngfft a priori different from ngfftrec)
2721 : !! rset<recursion_type> contains all parameter of recursion
2722 : !! typat(natom)=type of pseudo potential associated to any atom
2723 : !! natom=number of atoms
2724 : !! projec(ngfftrec(1),ngfftrec(2),ngfftrec(3),lmnmax,natom) is the vector, on the ngfftrec grid containing
2725 : !! the non-lacal projector $Y_{lm}(r-R_A)f_{lk}(r-R_A)
2726 : !!
2727 : !! OUTPUT
2728 : !! rho_out=result of the continued fraction multiplied by a multiplicator
2729 : !!
2730 : !! SIDE EFFECTS
2731 : !! un(:,:,:)=initial vector on the grid. it is changed in output
2732 : !!
2733 : !! NOTES
2734 : !! at this time :
2735 : !! - need a rectangular box (rmet diagonal matrix)
2736 : !!
2737 : !! SOURCE
2738 :
2739 0 : subroutine recursion_nl(exppot,un,rho_out,rset,ngfft, &
2740 0 : & tsmear,trotter,dim_trott,tol,typat,&
2741 : & natom,projec)
2742 :
2743 :
2744 : use m_linalg_interfaces
2745 :
2746 : !Arguments -------------------------------
2747 : !scalars
2748 : integer,intent(in) :: trotter,natom,dim_trott
2749 : real(dp),intent(in) :: tol,tsmear
2750 : type(recursion_type),intent(in) :: rset
2751 : real(dp), intent(out) :: rho_out
2752 : !arrays
2753 : integer,intent(in) :: typat(natom),ngfft(18)
2754 : real(dp),intent(in) :: exppot(0:ngfft(1)*ngfft(2)*ngfft(3)-1)
2755 : real(dp),intent(inout) :: un(0:rset%nfftrec-1)
2756 : real(dp),pointer :: projec(:,:,:,:,:)
2757 : !Local variables-------------------------------
2758 : !scalars
2759 : integer, parameter :: minrec = 3
2760 : integer :: irec,isign,ii
2761 : real(dp) :: bb,beta,mult,prod_b2,rtrotter
2762 : real(dp) :: inf_ucvol,pi_on_rtrotter,twortrotter,exp1
2763 : real(dp) :: exp2,error,errold
2764 : real(dp) :: switchu,switchimu
2765 : complex(dp) :: facrec0,cinv2rtrotter,coeef_mu
2766 : character(len=500) :: msg
2767 : type(mpi_type),pointer:: mpi_loc
2768 : !arrays
2769 : real(dp):: tsec(2)
2770 : real(dp):: inf_tr(3)
2771 0 : real(dp):: an(0:rset%min_nrec),bn2(0:rset%min_nrec)
2772 0 : real(dp):: vn(0:rset%nfftrec-1)
2773 0 : real(dp):: unold(0:rset%nfftrec-1)
2774 0 : real(dp):: Zvtempo(1:2,0:rset%nfftrec-1)
2775 0 : complex(dp) :: acc_rho(0:rset%min_nrec)
2776 0 : complex(dp) :: D(0:dim_trott),Dold(0:dim_trott)
2777 0 : complex(dp) :: N(0:dim_trott),Nold(0:dim_trott)
2778 :
2779 : ! *************************************************************************
2780 :
2781 0 : call timab(608,1,tsec) !--start time-counter: recursion_nl
2782 0 : if(rset%debug)then
2783 0 : msg=' '
2784 0 : call wrtout(std_out,msg,'COLL')
2785 : end if
2786 :
2787 : !##############################################################
2788 0 : beta = one/tsmear
2789 :
2790 : !--Rewriting the trotter parameter
2791 0 : rtrotter = max(half,real(trotter,dp))
2792 :
2793 : !--Initialisation of mpi
2794 0 : mpi_loc => rset%mpi
2795 :
2796 : !--Initialisation of metrics
2797 0 : inf_ucvol = rset%inf%ucvol
2798 0 : inf_tr = rset%inf%tr
2799 : mult = one !--In the case of the calculus of the NL-energy
2800 :
2801 : !--Initialisation of an,bn,un....
2802 0 : N = czero; D = cone
2803 0 : facrec0 = cone
2804 0 : Nold = czero; Dold = czero
2805 :
2806 0 : an = zero; bn2 = zero; bn2(0) = one
2807 0 : bb = zero; vn = zero; unold = zero
2808 :
2809 : !--Variables for optimisation
2810 0 : pi_on_rtrotter = pi/rtrotter
2811 0 : twortrotter = two*rtrotter
2812 0 : exp1 = exp((beta*rset%efermi)/(rtrotter))
2813 0 : exp2 = exp(beta*rset%efermi/(twortrotter))
2814 0 : cinv2rtrotter = cmplx(one/twortrotter,zero,dp)
2815 0 : coeef_mu = cmplx(one/exp2,zero,dp)
2816 :
2817 : !--Initialisation of accumulated density
2818 0 : acc_rho = czero
2819 : !--Initialisation of estimated error
2820 0 : prod_b2 = twortrotter/exp1
2821 0 : errold = zero
2822 :
2823 : !##############################################################
2824 : !--Main loop
2825 0 : maindo : do irec = 0, rset%min_nrec
2826 : ! --Get an and bn2 coef by the lanczos method
2827 :
2828 : ! --Computation of exp(-beta*V/8*p)*un
2829 0 : vn = exppot * un
2830 :
2831 : ! --First Non-local psp contribution: (Id+sum_atom E(r,r1))vn
2832 0 : call timab(608,2,tsec)
2833 0 : call vn_nl_rec(vn,natom,typat,rset%ngfftrec(:3),inf_ucvol,rset%nl,projec)
2834 0 : call timab(608,1,tsec)
2835 :
2836 : ! --Computation of exp(-beta*V/8*p)*un
2837 0 : vn = exppot * vn
2838 :
2839 : ! --Convolution with the Green kernel
2840 : ! --FFT of vn
2841 0 : isign = -1
2842 0 : call fourdp(1,Zvtempo,vn,isign,mpi_loc,rset%nfftrec,1,rset%ngfftrec,6)
2843 :
2844 : ! --F(T)F(vn)
2845 0 : do ii = 0,rset%nfftrec-1
2846 0 : switchu = Zvtempo(1,ii)
2847 0 : switchimu = Zvtempo(2,ii)
2848 0 : Zvtempo(1,ii) = switchu*rset%ZT_p(1,ii) - switchimu*rset%ZT_p(2,ii)
2849 0 : Zvtempo(2,ii) = switchu*rset%ZT_p(2,ii) + switchimu*rset%ZT_p(1,ii)
2850 : end do
2851 :
2852 : ! --F^-1(F(T)F(vn))
2853 0 : isign = 1
2854 0 : call fourdp(1,Zvtempo,vn,isign,mpi_loc,rset%nfftrec,1,rset%ngfftrec,6)
2855 :
2856 : ! --Computation of exp(-beta*V/2*p)*vn
2857 0 : vn = inf_ucvol * exppot * vn
2858 :
2859 : ! --Second Non-local psp contribution: (Id+sum_atom E(r,r1))vn
2860 0 : call timab(608,2,tsec)
2861 0 : call vn_nl_rec(vn,natom,typat,rset%ngfftrec(:3),inf_ucvol,rset%nl,projec)
2862 0 : call timab(608,1,tsec)
2863 :
2864 : ! --Computation of exp(-beta*V/8*p)*vn
2865 0 : vn = exppot * vn
2866 :
2867 :
2868 : ! --Multiplication of a and b2 coef by exp(beta*fermie/(2.d0*rtrotter)) must be done in the continued fraction computation
2869 : ! --Computation of a and b2
2870 0 : an(irec) = inf_ucvol*ddot(rset%nfftrec,vn,1,un,1) !--an must be positive real
2871 :
2872 : ! --We must compute bn2 and prepare for the next iteration
2873 0 : if(irec<rset%min_nrec)then
2874 0 : do ii = 0,rset%nfftrec-1
2875 0 : switchu = un(ii)
2876 0 : un(ii) = vn(ii)-an(irec)*un(ii)-bb*unold(ii)
2877 0 : unold(ii) = switchu
2878 0 : bn2(irec+1) = bn2(irec+1)+inf_ucvol*un(ii)*un(ii)
2879 : end do
2880 0 : bb = sqrt(bn2(irec+1))
2881 0 : un = (one/bb)*un
2882 : end if
2883 :
2884 : ! ######################################################
2885 : ! --Density computation
2886 : ! in order to make it possible to stop the recursion_nl at the
2887 : ! needed accuracy, without doing more recursion_nl loop than needed further developpement
2888 :
2889 : call trottersum(dim_trott,error,&
2890 : & prod_b2,pi_on_rtrotter,&
2891 : & facrec0,coeef_mu,exp1,&
2892 : & an(irec),bn2(irec),&
2893 0 : & N,D,Nold,Dold)
2894 :
2895 :
2896 0 : if(irec/=rset%min_nrec .and. irec>=minrec)then
2897 0 : if((bn2(irec+1)<tol14).or.(mult*error<tol.and.errold<tol)) exit
2898 : end if
2899 0 : errold = mult*error
2900 : end do maindo
2901 : !--Accumulated density
2902 0 : rho_out = mult*real(cone-sum(N/D)*cinv2rtrotter,dp)
2903 :
2904 0 : call timab(608,2,tsec) !--stop time-counter: recursion_nl
2905 :
2906 0 : end subroutine recursion_nl
2907 : !!***
2908 :
2909 :
2910 : !!****f* ABINIT/vn_nl_rec
2911 : !! NAME
2912 : !! vn_nl_rec
2913 : !!
2914 : !! FUNCTION
2915 : !! this routine computes the contribution to the vector vn, during
2916 : !! recursion, due to the non-local psp.
2917 : !!
2918 : !! INPUTS
2919 : !! vn(:,:,:)=the vector on the real-space grid.
2920 : !! inf_ucvol=volume of infinitesimal cell
2921 : !! natom=number of atoms
2922 : !! typat(natom)=the type of psps associated to the atoms
2923 : !! ngfftrec(3)=first 3 components of ngfftrec (truncated box, if different from ngfft) for the real-space grid
2924 : !! nlrec<type(nlpsprec_type)> in recursion_type containing information concerning psp
2925 : !! projec(ngfftrec(1),ngfftrec(2),ngfftrec(3),lmnmax,natom) is the vector, on the ngfftrec grid containing
2926 : !! the non-lacal projector $Y_{lm}(r-R_A)f_{lk}(r-R_A)
2927 : !!
2928 : !! OUTPUT
2929 : !! vn_nl(:,:,:)=the non_local contribution to vn
2930 : !!
2931 : !! NOTES
2932 : !!
2933 : !! SOURCE
2934 :
2935 0 : subroutine vn_nl_rec(vn,natom,typat,ngfftrec,inf_ucvol,nlrec,projec)
2936 :
2937 :
2938 : use m_linalg_interfaces
2939 :
2940 : !Arguments -------------------------------
2941 : !scalars
2942 : integer,intent(in) :: natom
2943 : real(dp),intent(in) :: inf_ucvol
2944 : type(nlpsprec_type),intent(in) :: nlrec
2945 : !arrays
2946 : integer,intent(in) :: ngfftrec(3),typat(natom)
2947 : real(dp),intent(in) :: projec(0:,0:,0:,1:,1:)
2948 : real(dp),intent(inout):: vn(0:ngfftrec(1)*ngfftrec(2)*ngfftrec(3)-1)
2949 : !Local variables-------------------------------
2950 : !scalars
2951 : integer :: iatom,nfftrec
2952 : integer :: jlmn,il,in,jn
2953 : integer :: ipsp,ilmn
2954 : integer :: npsp,lmnmax
2955 : real(dp):: vn_nl_loc
2956 : !arrays
2957 0 : real(dp):: vn_nl(0:ngfftrec(1)-1,0:ngfftrec(2)-1,0:ngfftrec(3)-1)
2958 0 : real(dp):: vtempo(0:ngfftrec(1)-1,0:ngfftrec(2)-1,0:ngfftrec(3)-1)
2959 : real(dp):: tsec(2)
2960 : ! *************************************************************************
2961 :
2962 0 : call timab(615,1,tsec)
2963 : !--Initialisation
2964 :
2965 0 : vn_nl = zero
2966 0 : npsp = nlrec%npsp
2967 0 : lmnmax = nlrec%lmnmax
2968 0 : nfftrec = product(ngfftrec)
2969 0 : vtempo(:,:,:) = reshape(source=vn,shape=ngfftrec(:3))
2970 :
2971 : !--Sum_iatom \int dr1 E(r-r_a,r1-r_a)vn(r1) *infucvol
2972 0 : do iatom=1,natom !--Loop on atoms
2973 0 : ipsp = typat(natom)
2974 :
2975 : ! --If psp(typat(iatom)) is local then cycle
2976 0 : if(all(nlrec%pspinfo(:,ipsp)==0)) cycle
2977 :
2978 :
2979 : ! write(std_out,*)'lmnmax',nlrec%lmnmax,lmnmax
2980 :
2981 0 : do ilmn = 1, lmnmax
2982 0 : do jlmn = 1,lmnmax
2983 0 : if(nlrec%indlmn(4,ilmn,ipsp)==nlrec%indlmn(4,jlmn,ipsp)) then
2984 0 : il = 1+nlrec%indlmn(1,jlmn,ipsp)
2985 0 : in = nlrec%indlmn(3,ilmn,ipsp)
2986 0 : jn = nlrec%indlmn(3,jlmn,ipsp)
2987 0 : vn_nl_loc = ddot(nfftrec,projec(:,:,:,jlmn,iatom),1,vtempo,1)
2988 0 : vn_nl = vn_nl+projec(:,:,:,ilmn,iatom)*vn_nl_loc*nlrec%mat_exp_psp_nl(in,jn,il,ipsp)
2989 : end if
2990 : end do
2991 : end do
2992 : end do !--End loop on atoms
2993 0 : vtempo = vtempo + vn_nl*inf_ucvol
2994 :
2995 0 : vn = reshape(source=vtempo,shape=(/nfftrec/))
2996 :
2997 0 : call timab(615,2,tsec)
2998 :
2999 0 : end subroutine vn_nl_rec
3000 : !!***
3001 :
3002 : end module m_vtorhorec
3003 : !!***
|